Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Voting for the Unity Awards are OPEN! We’re looking to celebrate creators across games, industry, film, and many more categories. Cast your vote now for all categories
    Dismiss Notice
  3. Dismiss Notice

Player Movement Script - Transform.forward is not always acting forward

Discussion in 'Scripting' started by aceaspadesblack, Mar 25, 2018.

  1. aceaspadesblack

    aceaspadesblack

    Joined:
    Dec 2, 2015
    Posts:
    14
    In the following script, I have used a mouse rotation to rotate the player, then horizontal/vertical input to generate player movement. However, when the script is used, an issue occurs: a difference of forward facing from forward movement. When I am faced in a certain direction, everything is fine, but as I begin to turn, the horizontal/vertical input does change with rotation, but at a different rate than the player is rotating, causing forward to become all sorts of directions that are not forward.

    How do I cause the player to always move properly forward with vertical input?



    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. public class PlayerController : MonoBehaviour
    4. {
    5.     void FixedUpdate()
    6.     {
    7.         float walkspeed = 2f;
    8.         float turnspeed = 2f;
    9.  
    10.         // mouse rotation
    11.         float mouseInput = Input.GetAxis("Mouse X");
    12.         Vector3 lookhere = new Vector3(0, mouseInput, 0) * turnspeed;
    13.         transform.Rotate(lookhere);
    14.  
    15.         // forward and right vectors:
    16.         var forward = transform.forward;
    17.         var right = transform.right;
    18.  
    19.         //reading input:
    20.         float horizontalAxis = Input.GetAxis("Horizontal");
    21.         float verticalAxis = Input.GetAxis("Vertical");
    22.  
    23.         //forward and right vectors on the horizontal plane
    24.         forward.y = 0f;
    25.         right.y = 0f;
    26.  
    27.         forward.Normalize();
    28.         right.Normalize();
    29.  
    30.  
    31.         //the direction in world space to move
    32.         var desiredMoveDirection = forward * verticalAxis + right * horizontalAxis;
    33.  
    34.         //apply movement
    35.         transform.Translate(desiredMoveDirection * walkspeed * Time.deltaTime);
    36.  
    37.     }
    38. }
     
  2. TJHeuvel-net

    TJHeuvel-net

    Joined:
    Jul 31, 2012
    Posts:
    817
    You can visualize your forward and right using Debug.DrawRay. Try doing this to see what changes you make to the vectors, so draw them just as you get them, when you set the y to 0 and when you normalize them.
     
  3. aceaspadesblack

    aceaspadesblack

    Joined:
    Dec 2, 2015
    Posts:
    14
    Thank you for your suggestion. I used Debug.DrawRay in the three locations you specified, to discover that nothing seems to be wrong with forward or right ; while the player turns, these remain true. However, still, while the character is moving, it is not always moving properly in the direction of forward.

    As MouseInput gives rotation to the player's Y axis, the direction of forward does always stay true, but the Keyboard movement input often does not send the player in the forward direction. This happens at specific directions; when player rotation is (0,0,0), pos/neg input to the vertical axis moves the player along the Z axis (world) , but when rotation is (0,45,0), pos/neg input to the vertical axis moves the player along the X axis (world); at (0,90,0), again pos/neg vertical axis input moves the player along the Z axis (world).
     
  4. StarManta

    StarManta

    Joined:
    Oct 23, 2006
    Posts:
    8,738
    This sounds like the rotation of the transform being used for "translation" is being rotated at double the rate as the rotation value of the object. This is odd, since you're using the Transform for both.

    However, it's possible the discrepancy is between the "world" rotation (which would determine the translation direction) and the "local" rotation (which you would see in the inspector). You may try this:
    Code (csharp):
    1. Debug.Log("local="+transform.localRotation+"     global="+transform.rotation);
    And see if these are indeed different values. (They'll be quaternions, not Euler angles, so don't worry if they're not the numbers you're expecting; just compare them to each other.) Does your object have any parents in the hierarchy? If so, check out their rotation values in the inspector. Is it possible you have extra copies of this script or maybe some other rotation script on one of the parents?
     
  5. aceaspadesblack

    aceaspadesblack

    Joined:
    Dec 2, 2015
    Posts:
    14

    I am getting a 1-for-1 exact match between local and world rotations. I believe you are correct in saying that "the rotation of the transform being used for translation is being rotated at double the rate of the rotation value of the object", as the difference of the player object Y rotation value to the translation on the X and Y axes stabilizes (somewhat) at exact intervals of 45 degrees at a time. I've broken up the different calculations in all sorts of ways but I cannot crack this problem.

    The PlayerController script is attached to the Player object. The Main Camera is a child of the Player, as well as other objects. There are no active scripts on the Child objects, other than stock components. The only other script being used in the project is a Billboard script that causes sprites to always turn and look towards the camera; deactivating/removing these scripts has no effect upon the current problem.

    Screen Shot 2018-03-27 at 12.07.47 AM.png
     
  6. aceaspadesblack

    aceaspadesblack

    Joined:
    Dec 2, 2015
    Posts:
    14
    Fixed!

    Code (CSharp):
    1.         transform.Translate(desiredMoveDirection * walkspeed * Time.deltaTime, Space.World);
    2.  
    It was not set to translate relativeTo world space. Thanks for the help, everyone!
     
  7. FirstTimeCreator

    FirstTimeCreator

    Joined:
    Sep 28, 2016
    Posts:
    768
    I completely wrote my own RB player controller from scratch. After getting into it you learn that it is far superior to the Character Controller because you can achieve the same things as the player controller with much more freedom.

    What I have done with mine is completely separate the camera from the capsule collider as a parent which gives me total freedom meaning i don't even need a forward direction (from capsule/gameobject) because the camera is used for the forward direction. The capsule can be rotated in way i wish as well as the camera... that's freedom!.

    I'm using it to walk on planets right now, aligning to normal's and what not.

    I would do away with that controller you have and switch to physics. Dont rotate your collider when your camera looks. get the direction the camera is looking on x,z and apply a force in that direction without even rotating the capsule.

    It also helps fix sticking to walls in certain scenarios if the PC capsule is turning in a corner for example.. no problems.