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

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?

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[RequireComponent(typeof(CharacterController))]

public class SC_TPSController : MonoBehaviour
{
    public float speed = 7.5f;
    public float jumpSpeed = 8.0f;
    public float gravity = 20.0f;
    public Transform playerCameraParent;
    public float lookSpeed = 2.0f;
    public float lookXLimit = 60.0f;
   

    CharacterController characterController;
    Vector3 moveDirection = Vector3.zero;
    Vector2 rotation = Vector2.zero;
   
    [HideInInspector]
    public bool canMove = true;

    void Start()
    {
        characterController = GetComponent<CharacterController>();
        rotation.y = transform.eulerAngles.y;
    }

    void Update()
    {
        if (characterController.isGrounded)
        {
            // We are grounded, so recalculate move direction based on axes
            Vector3 forward = transform.TransformDirection(Vector3.forward);
            Vector3 right = transform.TransformDirection(Vector3.right);
            float curSpeedX = canMove ? speed * Input.GetAxis("Vertical") : 0;
            float curSpeedY = canMove ? speed * Input.GetAxis("Horizontal") : 0;
            moveDirection = (forward * curSpeedX) + (right * curSpeedY);
           
       
           

            if (Input.GetButton("Jump") && canMove)
            {
                moveDirection.y = jumpSpeed;
            }
        }

        // Apply gravity. Gravity is multiplied by deltaTime twice (once here, and once below
        // when the moveDirection is multiplied by deltaTime). This is because gravity should be applied
        // as an acceleration (ms^-2)
        moveDirection.y -= gravity * Time.deltaTime;

        // Move the controller
        characterController.Move(moveDirection * Time.deltaTime);

        // Player and Camera rotation
        if (canMove)
        {
            rotation.y += Input.GetAxis("Mouse X") * lookSpeed;
            rotation.x += -Input.GetAxis("Mouse Y") * lookSpeed;
            rotation.x = Mathf.Clamp(rotation.x, -lookXLimit, lookXLimit);
            playerCameraParent.localRotation = Quaternion.Euler(rotation.x, 0, 0);
            transform.eulerAngles = new Vector2(0, rotation.y);
        }
    }
}

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:

var input = new Vector2( AXISH, AXISV);

if (input.magnitude >= 1.0f) input.Normalize();

// now do whatever you want with input.x and input.y, knowing their
// combined magnitude will never exceed 1.0

(I am lazy and did not type out AXISH/AXISV, it’s the code you did above)

I’m sorry. Know very little C#. Do I replace your AXISV with Input.GetAxis(“Vertical”)?

Yessir, I was just lazy, typing, not copying code.

It didn’t work :frowning: It’s still faster.

using UnityEngine;

public class PlayerMovement : MonoBehaviour
{
   
    public float speed = 7.5f;
    public float jumpSpeed = 8.0f;
    public float gravity = 20.0f;
    public Transform playerCameraParent;
    public float lookSpeed = 2.0f;
    public float lookXLimit = 60.0f;

    CharacterController characterController;
    Vector3 moveDirection = Vector3.zero;
    Vector2 rotation = Vector2.zero;

    [HideInInspector]
    public bool canMove = true;

    void Start()
    {
        characterController = GetComponent<CharacterController>();
        rotation.y = transform.eulerAngles.y;
    }

    void Update()
    {
        if (characterController.isGrounded)
        {
            // We are grounded, so recalculate move direction based on axes
            Vector3 forward = transform.TransformDirection(Vector3.forward);
            Vector3 right = transform.TransformDirection(Vector3.right);
            float curSpeedX = canMove ? speed * Input.GetAxis("Vertical") : 0;
            float curSpeedY = canMove ? speed * Input.GetAxis("Horizontal") : 0;
            var input = new Vector3( Input.GetAxis("Horizontal") , Input.GetAxis("Vertical") );
            if (input.magnitude >= 1.0f) input.Normalize();
            moveDirection = (forward * curSpeedX) + (right * curSpeedY);

            if (Input.GetButton("Jump") && canMove)
            {
                moveDirection.y = jumpSpeed;
            }
        }

        // Apply gravity. Gravity is multiplied by deltaTime twice (once here, and once below
        // when the moveDirection is multiplied by deltaTime). This is because gravity should be applied
        // as an acceleration (ms^-2)
        moveDirection.y -= gravity * Time.deltaTime;

        // Move the controller
        characterController.Move(moveDirection * Time.deltaTime);

        // Player and Camera rotation
        if (canMove)
        {
            rotation.y += Input.GetAxis("Mouse X") * lookSpeed;
            rotation.x += -Input.GetAxis("Mouse Y") * lookSpeed;
            rotation.x = Mathf.Clamp(rotation.x, -lookXLimit, lookXLimit);
            playerCameraParent.localRotation = Quaternion.Euler(rotation.x, 0, 0);
            transform.eulerAngles = new Vector2(0, rotation.y);
        }
    }
}

You didn’t actually use the newly-clamped values residing in the input vector.

This line:

moveDirection = (forward * curSpeedX) + (right * curSpeedY);

needs to instead of the curSpeed variables, use input.x and input.y appropriately:

moveDirection = (forward * input.x) + (right * input.y);

or perhaps:

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.