🤔

Diagonal movement and normalization#

If digital input is not normalized before it's used, it will be a different magnitude (length) when applied at a diagonal.

Picture the vector that makes up movement as a square, the magnitude of a vector at one of the corners of the square is 2\sqrt{2} (1.4142...)1, it should be 1 instead, which is achieved by normalization.

Interactive diagram#

Press the button below the diagram to toggle between unscaled and normalized values.

Unscaled

Resolution#

I want continuous 0->1 movement maintained from analog controls like joysticks#

Normalisation is not always desirable. If your input is analog—meaning it has continuous input values, not just 0 and 1—then you may just want to ensure it's within a 0->1 range by using ClampMagnitude.

Vector3 input = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));

// 🔴 Incorrect.
Vector3 movement = input * speed;

// 🟢 Correct, input is clamped to a max length of 1 before being scaled.
Vector3 movement = Vector3.ClampMagnitude(input, 1) * speed;

I want normalized movement (0 or 1) regardless of the controls#

For some games with strict controls it can be desirable to have digital movement. In this case you should normalize your input vector before using it.

Vector3 input = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));

// 🔴 Incorrect.
Vector3 movement = input * speed;

// 🟢 Correct, input is normalized before being scaled.
Vector3 movement = input.normalized * speed;
information

If you scale multiple float arguments with a vector you should multiply them together first with brackets: vector * (scalarA * scalarB).
This avoids extra multiplications.

  1. The magnitude of a 2D vector is x2+y2\sqrt{x^2 + y^2}. This is just the Pythagorean theorem applied to the triangle constructed by the two axes that are at a right angle to each other.