Search Unity

Player movement question from a beginner

Discussion in 'Scripting' started by ElMagnifico, Aug 11, 2020.

  1. ElMagnifico

    ElMagnifico

    Joined:
    Aug 27, 2018
    Posts:
    71
    So I started making my own 2.5 platformer and have run into quite a few problems.

    I got many of the basic systems working, but a few things are giving me issues. I'm using rigidbody and the z-axis as forward. Since the player is supposed to go in both directions and turn to face the direction he's walking towards.

    The way I went about it is below (player script, called in fixed update):

    Code (CSharp):
    1.         //horizontal movement
    2.         rigidBC.velocity = new Vector3(rigidBC.velocity.x, rigidBC.velocity.y, horizontalImput*walkSpeed);
    3.         animator.SetFloat("speed", (FacingSide * rigidBC.velocity.z) / walkSpeed);
    4.  
    5.         //facing by current rotation and horizontal imput
    6.         //0° on Y axis = postitive horizontal imput = right
    7.         //180° on Y axis = negative horizontal imput = left
    8.         if ((this.transform.rotation.y == 0) && (horizontalImput < 0))
    9.         {
    10.             Debug.Log("Moving right");
    11.             rigidBC.MoveRotation(Quaternion.Euler(new Vector3(0, 180, 0)));
    12.         }
    13.         if ((this.transform.rotation.y == 180) && (horizontalImput > 0))
    14.         {
    15.             Debug.Log("Moving left");
    16.             rigidBC.MoveRotation(Quaternion.Euler(new Vector3(0, -180, 0)));
    17.         }
    the player starts looking right (0° rotation) and rotates properly when I move left, but then never rotates back. (at this point I want to integrate a button that locks the facing, so you can back up while shooting forward)


    I tried using the same system inside my bullet script (so it fires in he direction the player is facing), but it doesn't work at all there, bullets always go right (I don't want to use mouse aiming, just regular old-school shoot straight forward)

    Code (CSharp):
    1.    public void Fire(Vector3 position, Vector3 euler, int layer)
    2.     {
    3.         lifeTimer = Time.time;
    4.         transform.position = position;
    5.         transform.eulerAngles = euler;
    6.         transform.position = new Vector3(0, transform.position.y, transform.position.z);
    7.         //transform.rotation = Quaternion.LookRotation(vop, Vector3.right);
    8.         transform.rotation = Quaternion.Euler(0f, 0f, 0f);
    9.  
    10.         if (this.transform.rotation.y == 0)
    11.         {
    12.             Vector3 vop = Vector3.ProjectOnPlane(transform.right, Vector3.right);
    13.             transform.right = vop;
    14.         }
    15.         if (this.transform.rotation.y == 180)
    16.         {
    17.             Vector3 vop = Vector3.ProjectOnPlane(transform.right, Vector3.left);
    18.             transform.right = vop;
    19.         }
    20.  
    21.     }

    I feel like an idiot. What am I missing here?
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,742
    You cannot compare floating point values for equality. You are doing this every time you compare the eulerAngles.y to something.

    Also, when you directly compare rotation.y, that is NOT what you think it is. That is NOT the angle around the y, but rather one of the four internal components of a quaternion: x, y, z, w. They are NOT angles. Don't mess with them, ever, there is simply never a call to touch those unless you're really doing clever weird mathy stuff.

    Generally, just stay away from reading quaternion .eulerAngles. They're ambiguous and imprecise and can cause all manner of bugs.

    Instead, to solve your problem, keep track of a desired angle you want to face. Left might be 180, right might be 0, or whatever, and when you press left or right you simply SET the desired angle, nothing else.

    Then have another variable tracking which way you are facing, your actual angle.

    Now every frame simply move the latter towards the former using Mathf.MoveTowardsAngle().

    Code (csharp):
    1. actualAngle = Mathf.MoveTowardsAngle( actualAngle, desiredAngle,
    2.                             MyIntendedRateOfTurn * Time.deltaTime);
    Finally, each frame,use that actual angle to produce a new rotation and set it:

    Code (csharp):
    1. transform.rotation = Quaternion.Euler( 0, actualAngle, 0);
    NOTE: there are no comparisons to make in the above code: you set the desired, you move the actual towards the desired, and you drive the rotation. It's very reliable that way.
     
  3. ElMagnifico

    ElMagnifico

    Joined:
    Aug 27, 2018
    Posts:
    71
    It's a 2.5D platformer, so rotation should be instant.
    If you're holding right arrow, the player should be rotated 0°.
    If you're holding left, he should be rotated 180°.

    But thanks you, I got it to work now. I'll be having a lot more questions soon. Trying ot make a game is both frustrating and rewarding.
     
  4. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,742
    Welcome to it!

    I highly recommend only accepting the rewarding part into your life.

    Use the frustrating part as a simple incentive / tool to improve your skills and abilities, nothing more, then drop it.
     
  5. ElMagnifico

    ElMagnifico

    Joined:
    Aug 27, 2018
    Posts:
    71
    OK, more questions time!
    Please be patient with me, the only time I touched coding was many, many years ago, and it was the very basic stuff.

    Now I'm stuggling with deciding on how to go about doing what I want, as I see many possibilities, but do not know which method to choose.
    The issues are with player weapons. He is supposed to be able to pick up and use various weapons. Now picking things up is easy enough - a simple trigger collider (collectable layer or tag, or perhaps a new layer/tag). But how to best handle them?

    My initial idea is to have every weapon defined within it's own weapon script, together with bullet prefab and muzzle being set.

    Code (CSharp):
    1.     public int maxAmmo;
    2.     public int currentAmmo;
    3.     public int rof;
    4.  
    5.     public string ammoType;
    6.     public GameObject bulletPrefab;
    7.     public Transform muzzleTransform;
    8.  
    9.     public bool isActive = false;
    10.     public bool isUnlocked = false;
    And the player would have the weapons game objects referenced:
    Code (CSharp):
    1.     private bool jumpKeyWasPressed;
    2.     private float horizontalImput;
    3.     private Rigidbody rigidBC;
    4.     private int specialsRemaining;
    5.     private int requisitionPoints;
    6.     private Animator animator;
    7.     private Camera mainCamera;
    8.     private float walkSpeed = 2.5f;
    9.     private int gravchuteUses = 0;
    10.     private bool currentFacingRight = true; // right or left checker
    11.  
    12.     [SerializeField] private Transform groundCheckTransform = null;
    13.     [SerializeField] private LayerMask playerMask;
    14.     public int Health;
    15.     public int Lives;
    16.     public GameObject bulletPrefab; // moved to individual weapon?
    17.     public Transform muzzleTransform; // moved to individual weapon?
    18.  
    19.     public GameObject Weapon1;
    20.     public GameObject Weapon2;
    21.     public GameObject Weapon3;
    22.     public GameObject Weapon4;
    23.     public GameObject Weapon5;
    24.  
    25.  
    Then either assign the weapon script to a weapon 3D model and have them prented the player hand on pickup, or have them all be part of the player model (just inactive). Then if picked up, it becomes unlocked and on weapon change keypress it can be activated.

    But how to best handle muzzle flash, bullet and weapons (and it's stats like RoF, damage ammo) in general?
    My biggest issue here is trying to fire out what I can call/access from where and how smart it is to do it that way.

    ATM, bullet is part of my player as he only has one weapon with infinite ammo, so it's relatively simple, but it suddenly becomes a clusterf*** when I add more. Defining everything inside the player is probably a bad idea, but now I have to track a lot of variable, check which weapon is active, pass argumnets to use to fire the damn thing, etc..

    A bit of a broad question.
     
  6. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,742
    No way I can capture all the nuances in this subject area, I won't even pretend.

    But I can suggest this: work through three tutorials from three different guys on Youtube and you will be amazed at all the different ways people tackle this stuff.

    From that you can begin to develop your own strategy, or if you prefer, reinvent the wheel and do it a whole new way!