Search Unity

I can't figure out how to fix diagonal movement with my script.

Discussion in 'Scripting' started by Dune333, Oct 27, 2020.

  1. Dune333

    Dune333

    Joined:
    Oct 13, 2020
    Posts:
    5
    I have the classic problem of diagonal movement being faster than other directions. I've looked at tutorials and tried to normalize and I'm tried to clamp the move input. When I apply code to clamp it just makes everything go super slow. Can anyone help me figure this out?


    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. [RequireComponent(typeof(CharacterController))]
    6.  
    7. public class SC_TPSController : MonoBehaviour
    8. {
    9.     public float speed = 7.5f;
    10.     public float jumpSpeed = 8.0f;
    11.     public float gravity = 20.0f;
    12.     public Transform playerCameraParent;
    13.     public float lookSpeed = 2.0f;
    14.     public float lookXLimit = 60.0f;
    15.    
    16.  
    17.     CharacterController characterController;
    18.     Vector3 moveDirection = Vector3.zero;
    19.     Vector2 rotation = Vector2.zero;
    20.    
    21.     [HideInInspector]
    22.     public bool canMove = true;
    23.  
    24.     void Start()
    25.     {
    26.         characterController = GetComponent<CharacterController>();
    27.         rotation.y = transform.eulerAngles.y;
    28.     }
    29.  
    30.     void Update()
    31.     {
    32.         if (characterController.isGrounded)
    33.         {
    34.             // We are grounded, so recalculate move direction based on axes
    35.             Vector3 forward = transform.TransformDirection(Vector3.forward);
    36.             Vector3 right = transform.TransformDirection(Vector3.right);
    37.             float curSpeedX = canMove ? speed * Input.GetAxis("Vertical") : 0;
    38.             float curSpeedY = canMove ? speed * Input.GetAxis("Horizontal") : 0;
    39.             moveDirection = (forward * curSpeedX) + (right * curSpeedY);
    40.            
    41.        
    42.            
    43.  
    44.             if (Input.GetButton("Jump") && canMove)
    45.             {
    46.                 moveDirection.y = jumpSpeed;
    47.             }
    48.         }
    49.  
    50.         // Apply gravity. Gravity is multiplied by deltaTime twice (once here, and once below
    51.         // when the moveDirection is multiplied by deltaTime). This is because gravity should be applied
    52.         // as an acceleration (ms^-2)
    53.         moveDirection.y -= gravity * Time.deltaTime;
    54.  
    55.         // Move the controller
    56.         characterController.Move(moveDirection * Time.deltaTime);
    57.  
    58.         // Player and Camera rotation
    59.         if (canMove)
    60.         {
    61.             rotation.y += Input.GetAxis("Mouse X") * lookSpeed;
    62.             rotation.x += -Input.GetAxis("Mouse Y") * lookSpeed;
    63.             rotation.x = Mathf.Clamp(rotation.x, -lookXLimit, lookXLimit);
    64.             playerCameraParent.localRotation = Quaternion.Euler(rotation.x, 0, 0);
    65.             transform.eulerAngles = new Vector2(0, rotation.y);
    66.         }
    67.     }
    68. }
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,742
    Put the check and clamp to normalize code in between line 38 and line 39.

    The check and clamp to normalize code must only operate on normalized data, ie., before you multiply it by your speed values.

    To do this you will have to combine the X and Y inputs into a Vector2 or Vector3, then pull them back out to do your other scaling by the speed.

    I like this approach:

    Code (csharp):
    1. var input = new Vector2( AXISH, AXISV);
    2.  
    3. if (input.magnitude >= 1.0f) input.Normalize();
    4.  
    5. // now do whatever you want with input.x and input.y, knowing their
    6. // combined magnitude will never exceed 1.0
    (I am lazy and did not type out AXISH/AXISV, it's the code you did above)
     
  3. Dune333

    Dune333

    Joined:
    Oct 13, 2020
    Posts:
    5
    I'm sorry. Know very little C#. Do I replace your AXISV with Input.GetAxis("Vertical")?
     
  4. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,742
    Yessir, I was just lazy, typing, not copying code.
     
  5. Dune333

    Dune333

    Joined:
    Oct 13, 2020
    Posts:
    5
    It didn't work :( It's still faster.

    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. public class PlayerMovement : MonoBehaviour
    4. {
    5.    
    6.     public float speed = 7.5f;
    7.     public float jumpSpeed = 8.0f;
    8.     public float gravity = 20.0f;
    9.     public Transform playerCameraParent;
    10.     public float lookSpeed = 2.0f;
    11.     public float lookXLimit = 60.0f;
    12.  
    13.     CharacterController characterController;
    14.     Vector3 moveDirection = Vector3.zero;
    15.     Vector2 rotation = Vector2.zero;
    16.  
    17.     [HideInInspector]
    18.     public bool canMove = true;
    19.  
    20.     void Start()
    21.     {
    22.         characterController = GetComponent<CharacterController>();
    23.         rotation.y = transform.eulerAngles.y;
    24.     }
    25.  
    26.     void Update()
    27.     {
    28.         if (characterController.isGrounded)
    29.         {
    30.             // We are grounded, so recalculate move direction based on axes
    31.             Vector3 forward = transform.TransformDirection(Vector3.forward);
    32.             Vector3 right = transform.TransformDirection(Vector3.right);
    33.             float curSpeedX = canMove ? speed * Input.GetAxis("Vertical") : 0;
    34.             float curSpeedY = canMove ? speed * Input.GetAxis("Horizontal") : 0;
    35.             var input = new Vector3( Input.GetAxis("Horizontal") , Input.GetAxis("Vertical") );
    36.             if (input.magnitude >= 1.0f) input.Normalize();
    37.             moveDirection = (forward * curSpeedX) + (right * curSpeedY);
    38.  
    39.             if (Input.GetButton("Jump") && canMove)
    40.             {
    41.                 moveDirection.y = jumpSpeed;
    42.             }
    43.         }
    44.  
    45.         // Apply gravity. Gravity is multiplied by deltaTime twice (once here, and once below
    46.         // when the moveDirection is multiplied by deltaTime). This is because gravity should be applied
    47.         // as an acceleration (ms^-2)
    48.         moveDirection.y -= gravity * Time.deltaTime;
    49.  
    50.         // Move the controller
    51.         characterController.Move(moveDirection * Time.deltaTime);
    52.  
    53.         // Player and Camera rotation
    54.         if (canMove)
    55.         {
    56.             rotation.y += Input.GetAxis("Mouse X") * lookSpeed;
    57.             rotation.x += -Input.GetAxis("Mouse Y") * lookSpeed;
    58.             rotation.x = Mathf.Clamp(rotation.x, -lookXLimit, lookXLimit);
    59.             playerCameraParent.localRotation = Quaternion.Euler(rotation.x, 0, 0);
    60.             transform.eulerAngles = new Vector2(0, rotation.y);
    61.         }
    62.     }
    63. }
    64.  
     
  6. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,742
    You didn't actually use the newly-clamped values residing in the
    input
    vector.

    This line:

    Code (csharp):
    1. moveDirection = (forward * curSpeedX) + (right * curSpeedY);
    needs to instead of the curSpeed variables, use input.x and input.y appropriately:

    Code (csharp):
    1. moveDirection = (forward * input.x) + (right * input.y);
    or perhaps:

    Code (csharp):
    1. moveDirection = (forward * input.y) + (right * input.x);
    The input axis ordering is unclear.

    Follow the data flow from input to use ... always follow the data flow.

    It also appears you may no longer need the curSpeed variables at all.