Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Small but frustrating player movement script bug

Discussion in 'Scripting' started by Falcoshin, Jul 20, 2017.

  1. Falcoshin

    Falcoshin

    Joined:
    May 31, 2017
    Posts:
    168
    I'm trying to create a player movement script and, for the most part, I think I have something that works. He moves where the input tells him to go and he'll turn in that direction. The problem, however, is that when there's no input detected, he'll only point to one of the 4 cardinal directions even if he was moving diagonally. I tried using a Logitech controller's joystick to see if the problem still existed and, while sometimes he would remain at the angle he was left at, most of the time he'd still end up at one of the cardinal directions.

    Here's a video explaining what I mean:



    And this is the code I have currently

    Code (csharp):
    1.  
    2. public class PlayerController : MonoBehaviour
    3. {
    4.  
    5.     CharacterController cc;
    6.     float turnVector;
    7.     Vector3 movement;
    8.  
    9.     void Start()
    10.     {
    11.         cc = GetComponent<CharacterController>();
    12.     }
    13.     ///*
    14.     void Update()
    15.     {
    16.         movement = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
    17.  
    18.         if (movement != Vector3.zero)
    19.         //if (movement.x > 0.01f || movement.z > 0.01f)
    20.         {
    21.             turnVector = Vector3.Angle(Vector3.forward, movement);
    22.             if (Input.GetAxis("Horizontal") < 0)
    23.             {
    24.                 turnVector = -turnVector;
    25.             }
    26.         }
    27.  
    28.  
    29.         transform.eulerAngles = new Vector3(0, turnVector, 0);
    30.         cc.Move(movement * Time.deltaTime);
    31.     }
    32.     //*/
    33.    
    34.  
    35.     void LateUpdate()
    36.     {
    37.        
    38.     }
    39. }
     
  2. cstooch

    cstooch

    Joined:
    Apr 16, 2014
    Posts:
    354
    If you were to actually look at the input values when stick was centred, you'd see a little fluctuation from zero. Just set the movement to Vector3.zero if the absolute value of the input Values are small.. maybe less than 0.2 or so.
     
    Last edited: Jul 20, 2017
  3. Laperen

    Laperen

    Joined:
    Feb 1, 2016
    Posts:
    1,065
    Not sure if this is overkill, but make another Vector3 detecting the input direction, but use GetAxisRaw instead. Use that in your "if" statement checking for movement instead.
     
  4. Falcoshin

    Falcoshin

    Joined:
    May 31, 2017
    Posts:
    168
    I tried something like that and, while it's closer to what I want, it still won't stay at the exact angle it's suppose to. If it's suppose to be at 135 degrees it will sometimes be 116 degrees.
     
  5. Falcoshin

    Falcoshin

    Joined:
    May 31, 2017
    Posts:
    168
    I'm not really sure I follow what you mean.
     
  6. cstooch

    cstooch

    Joined:
    Apr 16, 2014
    Posts:
    354
    Oh sorry, do you want exactly the 8 directions, nothing between? Normalize your vector. There is a normalize method, I believe on vector 3.. sorry I'm on mobile in a hotel, can't confirm at the moment.

    Sorry if I'm not completely understanding what you need.
     
  7. Falcoshin

    Falcoshin

    Joined:
    May 31, 2017
    Posts:
    168
    No, I want in-betweens. I just want it to stay where it's suppose to.
     
  8. Falcoshin

    Falcoshin

    Joined:
    May 31, 2017
    Posts:
    168
    I think a way of putting it is that it seems the input is WAY too sensitive. What I meant by what I said before is that, if I know for sure it's at 135 degrees and I suddenly stop, the input slowly scales back down and causes the angle to shift from that.
     
  9. cstooch

    cstooch

    Joined:
    Apr 16, 2014
    Posts:
    354
    Ahh ok. That might be a little tricky maybe. I'm guessing that as the stick is released the input values might deviate a bit from the angle you had it at or something. Going to have to think on that , a little. Maybe you might have to do something like if the vectors magnitude is less than it was in the last frame, ignore it?
     
  10. cstooch

    cstooch

    Joined:
    Apr 16, 2014
    Posts:
    354
    Or maybe even just ignore it only if the magnitude is less than a specific value ( experiment to figure out the value) if the suggestion above is a bit too extreme.
     
  11. Falcoshin

    Falcoshin

    Joined:
    May 31, 2017
    Posts:
    168
    Yeah, I'm trying the magnitude thing right now and that's what's causing what I described when I said that, If it's suppose to be at 135 degrees it will sometimes be 116 degrees.
     
  12. cstooch

    cstooch

    Joined:
    Apr 16, 2014
    Posts:
    354
    Sorry got to get to bed here now but maybe post the code where you attempted the magnitude idea and someone may see why that didn't quite work?
     
  13. Falcoshin

    Falcoshin

    Joined:
    May 31, 2017
    Posts:
    168
    Code (csharp):
    1.  
    2. public class PlayerController : MonoBehaviour
    3. {
    4.  
    5.     CharacterController cc;
    6.     float turnVector;
    7.     Vector3 movement;
    8.     Vector3 direction;
    9.  
    10.     void Start()
    11.     {
    12.         cc = GetComponent<CharacterController>();
    13.     }
    14.     ///*
    15.     void Update()
    16.     {
    17.         movement = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
    18.  
    19.         if (movement != Vector3.zero && movement.magnitude > 0.1f)
    20.         {
    21.             turnVector = Vector3.Angle(Vector3.forward, movement);
    22.             if (Input.GetAxis("Horizontal") < 0)
    23.             {
    24.                 turnVector = -turnVector;
    25.             }
    26.         }
    27.  
    28.  
    29.         transform.eulerAngles = new Vector3(0, turnVector, 0);
    30.         cc.Move(movement * Time.deltaTime);
    31.     }
    32.     //*/
    33.    
    34.  
    35.     void LateUpdate()
    36.     {
    37.        
    38.     }
    39. }
     
  14. Falcoshin

    Falcoshin

    Joined:
    May 31, 2017
    Posts:
    168
    Wasn't there a way to make Input.GetAxis snap back to zero if it's not detecting any input from that axis? Because there's something called "Snap" in the in input settings and I have it checked, but it's not doing anything.
     
  15. Laperen

    Laperen

    Joined:
    Feb 1, 2016
    Posts:
    1,065
    What I meant
    Code (csharp):
    1.  
    2. void Update()
    3. {
    4.     Vector3 forTurning = new Vector3(Input.GetAxisRaw("Horizontal"), 0, Input.GetAxisRaw("Vertical"));
    5.  
    6.     if (forTurning != Vector3.zero)
    7.     {
    8.         //do turning as before
    9.     }
    10. }
    11.  
     
  16. Falcoshin

    Falcoshin

    Joined:
    May 31, 2017
    Posts:
    168
    So you meant just using GetAxisRaw instead of GetAxis. I tried that, but it not only doesn't work, but the turning doesn't happen as smoothly as it does with the normal GetAxis which is the reason I'm using it in the first place.
     
  17. Laperen

    Laperen

    Joined:
    Feb 1, 2016
    Posts:
    1,065
    I meant, use GetAxisRaw for detecting if turning should occur, and nothing else.
     
  18. Falcoshin

    Falcoshin

    Joined:
    May 31, 2017
    Posts:
    168
    It's not turning that's the problem though. The problem is I need it to stay at the angle the character is theoretically suppose to be facing this way. In theory, I can't see how GetAxisRaw would allow me to do anything but increase the number of potential directions the character can end up facing from 4 to 8.
     
  19. Laperen

    Laperen

    Joined:
    Feb 1, 2016
    Posts:
    1,065
    GetAxis values gradually change, which is what is causing this problem in the first place.
    GetAxisRaw values can only either be 0 or 1.

    I'm not asking you to change from using GetAxis to GetAxisRaw, I'm simply recommending to use GetAxisRaw on a completely different Vector3 to check if the player is moving the toggle stick.
     
  20. cstooch

    cstooch

    Joined:
    Apr 16, 2014
    Posts:
    354
    This suggestion was a fair bit different than the one you did. I think my suggestion is a bit hoakey of a workaround though and there must be a better way, tbh. But it might work.

    https://docs.unity3d.com/Manual/class-InputManager.html

    As for snap, the manual says that is for keyboard/mouse. You can try adjusting dead (dead zone) maybe. I think I suggested that through code earlier, but the input manager is easier by the looks of it.
     
  21. Falcoshin

    Falcoshin

    Joined:
    May 31, 2017
    Posts:
    168
    I think I figured out what you mean and it appears to be working for the time being. Does your solution look something like this?

    Code (csharp):
    1.  
    2. public class PlayerController : MonoBehaviour
    3. {
    4.  
    5.     CharacterController cc;
    6.     float turnVector;
    7.     Vector3 movement;
    8.     Vector3 direction;
    9.  
    10.     void Start()
    11.     {
    12.         cc = GetComponent<CharacterController>();
    13.     }
    14.     ///*
    15.     void Update()
    16.     {
    17.         movement = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
    18.  
    19.         if (Input.GetAxisRaw("Horizontal") != 0 || Input.GetAxisRaw("Vertical") != 0)
    20.         {
    21.             turnVector = Vector3.Angle(Vector3.forward, movement);
    22.             if (Input.GetAxis("Horizontal") < 0)
    23.             {
    24.                 turnVector = -turnVector;
    25.             }
    26.         }
    27.  
    28.  
    29.         transform.eulerAngles = new Vector3(0, turnVector, 0);
    30.         cc.Move(movement * Time.deltaTime);
    31.     }
    32.     //*/
    33.    
    34.  
    35.     void LateUpdate()
    36.     {
    37.        
    38.     }
    39. }
     
  22. Laperen

    Laperen

    Joined:
    Feb 1, 2016
    Posts:
    1,065
    Yes that's it.