Lesson 20 +10 XP

Vector Math & Movement

Vector Math & Movement

Almost all movement, placement, and direction in 3D and 2D games relies on vectors. Unity handles this using the Vector3 (3D) and Vector2 (2D) structs.

1. Vector3 Coordinates and Direction

A Vector3 contains three float variables: x, y, and z. It represents either a coordinate location in the world or a relative direction.

  • Coordinates: A point like new Vector3(2f, 0f, 5f) places an object 2 units right and 5 units forward from the world origin.
  • Direction Constants:
  • Vector3.forward = new Vector3(0, 0, 1)
  • Vector3.up = new Vector3(0, 1, 0)
  • Vector3.right = new Vector3(1, 0, 0)

2. The Diagonal Movement Bug (Normalization)

If a player inputs forward movement (1 unit) and right movement (1 unit) simultaneously, the resulting combined vector length is 1.41 (calculated via Pythagoras). This means characters would run 41% faster diagonally! To fix this, you must normalize the input vector. Normalization shrinks the vector's total length to exactly 1 while preserving the direction:

using UnityEngine;

public class BasicMovement : MonoBehaviour
{
    [SerializeField] private float speed = 5.0f;

    void Update()
    {
        // 1. Get raw input values (-1.0 to 1.0)
        float horizontal = Input.GetAxisRaw("Horizontal");
        float vertical = Input.GetAxisRaw("Vertical");

        // 2. Create direction vector
        Vector3 inputDirection = new Vector3(horizontal, 0f, vertical);

        // 3. Prevent diagonal speed boost by normalizing
        if (inputDirection.magnitude > 1f)
        {
            inputDirection.Normalize();
        }

        // 4. Translate the GameObject's position
        transform.Translate(inputDirection * speed * Time.deltaTime);
    }
}

3. Understanding Time.deltaTime

The property Time.deltaTime returns the time in seconds it took to process the previous frame:

  • At 60 FPS, Time.deltaTime is roughly 0.016 seconds.
  • At 30 FPS, it is roughly 0.033 seconds.
  • If you move an object by 5f per frame, a player running at 60 FPS will move twice as fast as someone running at 30 FPS.
  • Multiplying by Time.deltaTime converts frame-based movement to time-based movement, guaranteeing that the object moves exactly 5 units per second on all computers, regardless of frame-rate.

4. Interpolation: Lerp and Slerp

Interpolation is used to smoothly transition between two values:

  • Vector3.Lerp(Vector3 start, Vector3 end, float t): Linearly moves in a straight line from start to end. The factor t is clamped between 0 and 1:
  • t = 0.0f returns the start vector.
  • t = 0.5f returns the midpoint.
  • t = 1.0f returns the end vector.
  • Vector3.Slerp(Vector3 start, Vector3 end, float t): Spherical linear interpolation. It treats the vectors as directions rather than points, moving along a curved arc. This is highly effective for smooth rotations.
// Smoothly slides an object toward a target point over time
transform.position = Vector3.Lerp(transform.position, targetPosition, Time.deltaTime * lerpSpeed);

TL;DR

  • Vector3 structs represent points in space or relative directions.
  • Always normalize multi-axis inputs to prevent diagonal speed boosts.
  • Multiply translation offsets by Time.deltaTime to ensure frame-rate independence.
  • Use Lerp for smooth straight-line movement transitions.
  • Use Slerp for smooth curved rotation sweeps.