🤔 Unity, huh, how?

🤔

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.