Diagonal movement is quicker

Help As the title says, I can’t seem to understand how to fix the faster move speed when moving diagonally. I have tried to search for a solution but nothing is working for me.

    public Rigidbody rb;
    float MouseSensitivity;
    float MoveSpeed =.375f;
    float JumpForce =10f;


    void Update()
    {

        rb.MovePosition(transform.position + (transform.forward * Input.GetAxis("Vertical") * MoveSpeed) + (transform.right * Input.GetAxis("Horizontal") * MoveSpeed));
        if (Input.GetKeyDown("space"))
            rb.AddForce(transform.up * JumpForce,ForceMode.Impulse);
    }

If possible an explanation to why this happens would be great also.

You need to normalize the direction vector you construct from the input axes.

To illustrate, let’s look only at the positive side of Vertical and Horizontal inputs and assume they’re either 0 or 1. In this case, you can get four different direction vectors:
(0, 0, 0) → No input → length 0
(0, 0, 1) → only Vertical → length 1
(1, 0, 0) → only Horizontal → length 1
(1, 0, 1) → Horizontal & Vertical → length 1.41

As you can see, when both inputs are active, the length of the direction vector is bigger than if only one of the inputs is active. This is what causes your diagonal speed to be ~40% faster.

You can think of it in terms of a square. The single inputs vectors are just along the sides of the square but when both are active, the vector is along the diagonal of the square. The diagonal is 1.41 times longer than the sides.

Normalizing the vector makes sure its length is always 1 and that when you multiply it with MoveSpeed, its length will always equal MoveSpeed as well.

You also need to multiply with Time.deltaTime (and adjust your MoveSpeed accordingly), otherwise your movement speed will change depending on the frame rate.

var direction = transform.forward * Input.GetAxis("Vertical") + transform.right * Input.GetAxis("Horizontal");
direction.Normalize();
rb.MovePosition(transform.position + direction * MoveSpeed * Time.deltaTime);
5 Likes

I agree with 100% of what @Adrian posted above, but I want to add one extra thing:

You may wish to allow slower-than-maximum motion, and in that case, change line 2 above in Adrian’s code to instead be:

if (direction.magnitude > 1.0f)
{
  direction.Normalize();
}

That way you can move at slower rates, and yet once you reach max, you’ll never exceed max, as Adrian’s code originally enforces.

1 Like

There’s also the helpful Vector3.ClampMagnitude which you can apply at the end to the result of any 1000 step direction calculation. Unity - Scripting API: Vector3.ClampMagnitude