In this lesson, you will learn how to synchronize your character’s movement logic with the physics engine’s internal clock to ensure consistent behavior across different hardware and frame rates.
The Physics Timing Problem
In Unity, the Update() method runs once per frame. Because frame rates vary—someone might be running your game at 60 FPS while another is at 144 FPS—any physics calculations performed inside Update() will execute a different number of times per second depending on the player's computer. This causes physics-based movement, like jumping or pushing objects, to feel "faster" or "slower" on different machines.
Using FixedUpdate
To solve this, we use the FixedUpdate() method. Unlike Update(), FixedUpdate() is called at a strictly consistent time interval (by default, every 0.02 seconds). The physics engine processes its calculations in these same discrete, reliable steps. By placing our Rigidbody logic inside FixedUpdate(), we ensure that our character’s movement is mathematically identical regardless of the player's frame rate.
Implementation Example
When moving a character with Rigidbody.AddForce or modifying Rigidbody.velocity, you should always move that code out of Update() and into FixedUpdate().
private Rigidbody rb;
private Vector3 movementInput;
void FixedUpdate()
{
// Apply movement forces here so the physics engine
// processes them at a steady, predictable interval.
Vector3 force = movementInput * speed;
rb.AddForce(force, ForceMode.Acceleration);
}
Keeping Inputs Separate
A common mistake is putting input gathering inside FixedUpdate(). Because FixedUpdate() runs at a fixed interval, it might skip frames where an input was pressed or missed, leading to "mushy" controls. The best practice is to read your input (using your knowledge of the Input System) inside Update() to store the value, then apply that stored value to the Rigidbody inside FixedUpdate(). This keeps your controls responsive while keeping your physics stable.
Key Takeaway: Always process Rigidbody forces and velocity changes inside FixedUpdate to ensure physics behavior remains consistent across all hardware.