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. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

Diagonal movement speed to fast

Discussion in 'Scripting' started by Kovenant, Oct 1, 2014.

  1. Kovenant

    Kovenant

    Joined:
    Sep 18, 2013
    Posts:
    254
    Hi. I'm working on a fps-controller and as I'm pressing both the horizontal and vertical axis-keys to move diagonal; the speed of the run is to fast. Is there a simple, effective way to prevent this? I've googled a bit but nothing seems to help me out here; I'm just finding alot of mathematical calculations and well.. I'm to stupid for that bs.. ;)

    Here's my code:
    Code (JavaScript):
    1. var walkAcceleration : float = 15000;
    2. var runAcceleration : float = 30000;
    3.  
    4. var running : boolean = true;
    5.  
    6. var walkAccelAirRatio : float = 0.1;
    7.  
    8. @HideInInspector var walkDeaccelerationVolX : float;
    9. @HideInInspector var walkDeaccelerationVolZ : float;
    10.  
    11. var maxWalkSpeed : float = 4;
    12.  
    13. var jumpVelocity : float = 195;
    14.  
    15. var grounded : boolean = false;
    16. @HideInInspector var maxSlope : float = 60;
    17. @HideInInspector var horizontalMovement : Vector2;
    18.  
    19. var cameraObject : GameObject;
    20.  
    21. function Update()
    22. {
    23.     horizontalMovement = Vector2(rigidbody.velocity.x, rigidbody.velocity.z);
    24.     if(horizontalMovement.magnitude > maxWalkSpeed)
    25.     {
    26.         horizontalMovement = horizontalMovement.normalized;
    27.         horizontalMovement *= maxWalkSpeed;
    28.     }
    29.  
    30.     rigidbody.velocity.x = horizontalMovement.x;
    31.     rigidbody.velocity.z = horizontalMovement.y;
    32.    
    33.     if(grounded)
    34.     {
    35.         rigidbody.velocity.x = Mathf.SmoothDamp(rigidbody.velocity.x, 0, walkDeaccelerationVolX, 0);
    36.         rigidbody.velocity.z = Mathf.SmoothDamp(rigidbody.velocity.z, 0, walkDeaccelerationVolZ, 0);
    37.     }
    38.  
    39.     transform.rotation = Quaternion.Euler(0, cameraObject.GetComponent(MLookScript).currentYRotation, 0);
    40.    
    41.     if(Input.GetButton("Walk"))
    42.         running = false;
    43.     else if(Input.GetButtonUp("Walk"))
    44.         running = true;
    45.        
    46.     if(grounded && running)
    47.         rigidbody.AddRelativeForce(Input.GetAxis("Horizontal") * runAcceleration * Time.deltaTime, 0, Input.GetAxis("Vertical") * runAcceleration * Time.deltaTime);
    48.     else if(grounded && !running)
    49.         rigidbody.AddRelativeForce(Input.GetAxis("Horizontal") * walkAcceleration * Time.deltaTime, 0, Input.GetAxis("Vertical") * walkAcceleration * Time.deltaTime);
    50.     else
    51.         rigidbody.AddRelativeForce(Input.GetAxis("Horizontal") * walkAcceleration * walkAccelAirRatio * Time.deltaTime, 0, Input.GetAxis("Vertical") * walkAcceleration * walkAccelAirRatio * Time.deltaTime);
    52.    
    53.    
    54.    
    55.     if(Input.GetButtonDown("Jump") && grounded)
    56.         rigidbody.AddForce(0, jumpVelocity, 0);
    57. }
    58.  
    59. function OnCollisionStay(collision : Collision)
    60. {
    61.     for(var contact : ContactPoint in collision.contacts)
    62.     {
    63.         if(Vector3.Angle(contact.normal, Vector3.up) < maxSlope)
    64.             grounded = true;
    65.     }
    66. }
    67.  
    68. function OnCollisionExit()
    69. {
    70.     grounded = false;
    71. }
     
  2. Cpt Chuckles

    Cpt Chuckles

    Joined:
    Dec 31, 2012
    Posts:
    86
    you should gather your direction vector first, normalize it, and then set it to your movement speed.

    Code (csharp):
    1. Vector3 move = new Vector3(Input.GetAxis("Horizontal"), 0f, Input.GetAxis("Vertical"));
    2. move = move.normalized * Time.deltaTime * //walkspeed, runspeed, etc.
    3. rigidbody.AddRelativeForce(move);
     
  3. Kovenant

    Kovenant

    Joined:
    Sep 18, 2013
    Posts:
    254
    Thank you! I will give it a try!
     
  4. cranky

    cranky

    Joined:
    Jun 11, 2014
    Posts:
    180
    Normalizing it isn't always the best solution. If you're using a keyboard, it's fine. But with an analog stick, it will always force the length of the vector to be 1, so you won't be able to move slowly. Instead, get the length of the vector and see if it's greater than 1. If so, divide the movement vector by the length.
     
  5. Ultroman

    Ultroman

    Joined:
    Mar 10, 2014
    Posts:
    105
    Since this is the first hit you get, when searching for "unity diagonal movement faster" on Google, I thought I'd add what finally fixed the problem for me.

    1. Use cranky's solution above (thanks)
    ...AND...
    2. Make sure the "Sensitivity" of your analog stick axes is set to no more than 1!

    Mine were set to 2 for some reason (damn copy/pasting from old projects), so even when using cranky's fix, I had inputs of (1f, 1f) when within ~30 degrees of either diagonal, while holding the stick to its extremity. This made me think there might be some input-multiplier...and voila, sensitivity was the culprit.
     
  6. cranky

    cranky

    Joined:
    Jun 11, 2014
    Posts:
    180
    I know this thread is pretty old, but I would like to add that if you use GetAxisRaw instead of GetAxis, sensitivity, smoothing, and other processing won't be added, and you'll get raw input on the axis.
     
    Ultroman likes this.
  7. Slater7

    Slater7

    Joined:
    Oct 10, 2018
    Posts:
    11
    It's a bit late, but I'm not sure which vector length to get to see if it's greater than 1.
    A code example would be helpful.
     
  8. kdgalla

    kdgalla

    Joined:
    Mar 15, 2013
    Posts:
    4,365
    It's whatever your up/down/left/right input is.
     
  9. slumtrimpet

    slumtrimpet

    Joined:
    Mar 18, 2014
    Posts:
    372
    Code (CSharp):
    1. this._inputs = Vector3.zero;
    2. this._inputs.x = Input.GetAxis("Horizontal");
    3. this._inputs.z = Input.GetAxis("Vertical");
    4. if(this._inputs.magnitude > 1)
    5.   this._inputs = this._inputs.normalized;
     
    fatih3598 likes this.
  10. nat42

    nat42

    Joined:
    Jun 10, 2017
    Posts:
    353
    I know it's sample code and clarity matters, but it seems a bit wasteful not compare against sqrMagnitude instead and save a squareroot in the common case (and not reuse the magnitude or sqrMagnitude used in the condition in normalising the value)
     
  11. slumtrimpet

    slumtrimpet

    Joined:
    Mar 18, 2014
    Posts:
    372
    Nah, no worries... good point. :) How about we trust Unity to do this reasonably for us then?

    Code (CSharp):
    1. this._inputs = Vector3.zero;
    2. this._inputs.x = Input.GetAxis("Horizontal");
    3. this._inputs.z = Input.GetAxis("Vertical");
    4. this._inputs = Vector3.ClampMagnitude(this._inputs, 1f);
     
  12. NikTyllis

    NikTyllis

    Joined:
    Sep 24, 2018
    Posts:
    1
    If you have a max speed variable you can calculate the diagonal velocity with Pythagoras in an if statement such as below:

    if (Mathf.Sqrt(Mathf.Pow(rb.velocity.x, 2) + Mathf.Pow(rb.velocity.z, 2)) > maxSpeed)
    {
    //Slow down the speed with preferred method
    }
     
    yust likes this.
  13. miguosaliba

    miguosaliba

    Joined:
    Mar 5, 2020
    Posts:
    1
    This solution was the best for me, it keeps the smoothing and also keeps the speed constant. it also doesnt look choppy, thank you
     
  14. Mahian

    Mahian

    Joined:
    May 7, 2020
    Posts:
    1
    lifesaver