Broken Weapons and Transforms

After implementing the different weapon prefabs and bow/mouse aiming, my sword now will only point left and the bow will only move slightly rather than opposing my mouse position if i circle the player.

Character not flipping the sword:
image

It’s hard to show the mouse cursor/bow issue as screenshots dont capture the cursor. But if its close to the left of the character, the bow is on the left side of the character, if the cursor is far to the left of the character, the bow is on the right of the character.

The bow does aim correctly if the cursor moves around the edge of my screen, but if it’s close to the player it doesnt seem to behave correctly.

Not sure where i would begin to look at code to troubleshoot this. Any help appreciated

Active Inventory Class:

 using System.Collections;
 using System.Collections.Generic;
 using UnityEngine;
 
 public class ActiveInventory : MonoBehaviour
 { 
     private int activeSlotIndexNum = 0; 
     private PlayerControls playerControls; 

     private void Awake(){
          playerControls = new PlayerControls(); 
     }
 
     private void Start(){
         playerControls.Inventory.Keyboard.performed += ctx => ToggleActiveSlot((int)ctx.ReadValue<float>()); 
         ToggleActiveHighlight(0); 
     }
 
     private void OnEnable(){
          playerControls.Enable(); 
     }
  
     private void ToggleActiveSlot(int numValue){ 
         ToggleActiveHighlight(numValue - 1); 
     }
 
     private void ToggleActiveHighlight(int indexNum){ 
         activeSlotIndexNum = indexNum; 
         foreach(Transform inventorySlot in this.transform) { 
             { 
                 inventorySlot.GetChild(0).gameObject.SetActive(false); 
             } 
             this.transform.GetChild(indexNum).GetChild(0).gameObject.SetActive(true);
             ChangeActiveWeapon(); 
         }
      }
 
     private void ChangeActiveWeapon(){
 
         if(ActiveWeapon.Instance.CurrentActiveWeapon != null) 
         { 
             Destroy(ActiveWeapon.Instance.CurrentActiveWeapon.gameObject); 
         } 
         if(!transform.GetChild(activeSlotIndexNum).GetComponentInChildren<InventorySlot>()) 
         {
             ActiveWeapon.Instance.WeaponNull();
             return; 
         }
         GameObject weaponToSpawn = transform.GetChild(activeSlotIndexNum). 
         GetComponentInChildren<InventorySlot>().GetWeaponInfo().weaponPrefab;
         GameObject newWeapon = Instantiate(weaponToSpawn, ActiveWeapon.Instance.transform.position, Quaternion.identity);

         ActiveWeapon.Instance.transform.rotation = Quaternion.Euler(0,0,0);
         newWeapon.transform.parent = ActiveWeapon.Instance.transform;

         ActiveWeapon.Instance.NewWeapon(newWeapon.GetComponent<MonoBehaviour>());
      } 
 }

The actual handling of directions for the various weapons are in their specific scripts, Sword, Staff, etc.

Let’s take a look at your Sword.cs script and we’ll see if that shows the issue.

For formatting code, rather than using the > model, follow the instructions below:

Thanks Brian :slight_smile:

i changed the directional facing to be based on character movement rather than the mouse pointer which worked fine - i cant see that this would interfere but maybe you’ll see something different.

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

public class Sword : MonoBehaviour, IWeapon

{

    private Transform weaponCollider;

    private Animator myAnimator;

    private GameObject slashAnim;

   

    [SerializeField] private GameObject slashAnimPrefab;

    [SerializeField] private Transform slashAnimSpawnPoint;

    [SerializeField] private float swordAttackCD = .5f;

    private void Awake() {

        myAnimator = GetComponent<Animator>();  

    }  

    private void Start() {

        weaponCollider = PlayerController.Instance.GetWeaponCollider();

        slashAnimSpawnPoint = GameObject.Find("SlashAnimationSpawnPoint").transform;    

        }

    private void Update(){

        MouseFollowWithOffset();

    }

    public void Attack(){

       

            //isAttacking = true;

            myAnimator.SetTrigger("Attack");

            weaponCollider.gameObject.SetActive(true);

            slashAnim = Instantiate(slashAnimPrefab, slashAnimSpawnPoint.position, Quaternion.identity);

            slashAnim.transform.parent = this.transform.parent;

            StartCoroutine(AttackCDRoutine());

       

    }

    private IEnumerator AttackCDRoutine(){

        yield return new WaitForSeconds(swordAttackCD);

        ActiveWeapon.Instance.ToggleIsAttacking(false);

    }

    public void DoneAttackingAnimEvent(){

        weaponCollider.gameObject.SetActive(false);

    }

    public void SwingUpFlipAnim(){

        slashAnim.gameObject.transform.rotation = Quaternion.Euler(-180,0,0);

        if(PlayerController.Instance.FacingLeft){

            slashAnim.GetComponent<SpriteRenderer>().flipX = true;

        }

    }

    public void SwingDownFlipAnim(){

        slashAnim.gameObject.transform.rotation = Quaternion.Euler(0,0,0);

        if(PlayerController.Instance.FacingLeft){

            slashAnim.GetComponent<SpriteRenderer>().flipX = true;

        }

    }

    private void MouseFollowWithOffset(){

        //Vector3 mousePos = Input.mousePosition;

        //Vector3 playerScreenPoint = Camera.main.WorldToScreenPoint(playerController.transform.position);

        float moveInput = Input.GetAxisRaw("Horizontal");

        if(moveInput < 0)

        {

            ActiveWeapon.Instance.transform.rotation = Quaternion.Euler(0, -180, 0);

            weaponCollider.transform.rotation = Quaternion.Euler(0, -180, 0);

        }

        else if(moveInput > 0){

            ActiveWeapon.Instance.transform.rotation = Quaternion.Euler(0, 0, 0);

            weaponCollider.transform.rotation = Quaternion.Euler(0, 0, 0);

        }

    }

}

With this code, the sword will never do more than face left or right, but never actually change anything with the mouse, including aiming.
I’m not sure, however, why it wouldn’t move left and right as your character moves left or right as mentioned at the top of your initial post (and you seem to be saying it’s working fine now?)

As the course is setup using the New Input System, are you getting any error messages concerning the Input.GetAxisRaw(“Horizontal”)?

Let’s add a Debug

float moveInput = Input.GetAxisRaw("Horizontal");
Debug.Log($"Horizontal = {moveInput}");
if(moveInput<0)
{
    Debug.Log($"Moving Left");
    //rest of code
}
else if(moveInput>0)
{
    Debug.Log($"Moving Right");
    //rest of code
}

Hey again, Brian,

Yeah the IF statements are firing fine, no error logs, console messages fire as expected. Obviously the bow will need mouse movement to aim so would assume a method in the bow class would override.

image

However, had a look at the classes attached to the Active Weapon game object in the hierarchy and Mouse Follow was on there, sure id have put that on to follow the steps in the vid but obviously this conflicts with the directional facing based on move direction rather than mouse position.

Suppose I could do something like add an if statement there for the facemouse method that if activeweapon slot != 0

I should have slept on it before commenting, sometimes all you need is more mental bandwidth to look with fresh eyes :sweat_smile:

Although im struggling to see how i could check if the weapon is the sword then not to apply the mouse follow - though the bow maybe is being interfered with due to the directional facing and why it isnt moving properly. Is there a way to separate these out? Or would that require a different kind of code game setup? im thinking it would.

for example, it would require each weapon in the hierarchy and as you toggle through the weapons it enables and disables accordingly and changes the sprite, but in each one the hierarchy has different attack and key/mouse tracking scripts attached to it?

Let’s take a look at your bow method.

The bow class just has an empty public void Attack() method for implementing the IWeapon interface. Other than that it’s empty which i think for this point of the tutorial is what it should be?

I tried reverting to the cursor based positioning for the sword method but it didnt affect the bow not rotating correctly.

You’re right, I was thinking of the MouseFollow.
Compare it with this script:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MouseFollow : MonoBehaviour
{
    private void Update() {
        FaceMouse();
    }

    private void FaceMouse() {
        Vector3 mousePosition = Input.mousePosition;
        mousePosition = Camera.main.ScreenToWorldPoint(mousePosition);

        Vector2 direction = transform.position - mousePosition;

        transform.right = -direction;
    }
}

and make sure that it’s on the same GameObject as the ActiveWeapon

Ah fair. MF and Aw attached to active weapon object:
image

Mouse Follow class below. Not sure why the bow wouldnt rotate correctly, but i get the concept and can live with it for the sake of the tutorial. ill just use the sword.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MouseFollow : MonoBehaviour
{
    private void Update(){
        FaceMouse();
    }

    private void FaceMouse(){
        Vector3 mousePosition = Input.mousePosition;
        mousePosition = Camera.main.WorldToScreenPoint(mousePosition);

        Vector2 direction = transform.position - mousePosition;

        transform.right = -direction;
    }
}

I noticed a difference in the two versions of MF. Brian has

mouse Position = Camera.main.ScreenToWorldPoint(mousePosition);

You have

mouse Position = Camera.main.WorldToScreenPoint(mousePosition);

I have not taken this course but I think this might be part of the issue. Hope this helps.

I think this is it, entirely. WorldToScreenPoint(mousePosition) would convert our world scale (depending on your setup around ±20,±15) to Screen point which will

  • Always be positive
  • Will be on a MUCH larger scale, as it represents pixels on your game window, not World Units.

Try changing this to ScreenToWorldPoint, and I think you’ll see improved results.

This absolutely sorted it, thank you both, and thanks for the explanation. Cant believe i missed that!

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.

Privacy & Terms