AnyLearn
All lessons
Programmingintermediate

Unity: physics and the fixed timestep

Why Unity runs physics on its own 50Hz clock instead of the frame rate, and what follows from that. Covers rigidbodies and colliders, moving things correctly with forces rather than the Transform, interpolation for smooth motion, tunneling and continuous collision detection, and where physics cost actually comes from.

Updated · AI-authored, review-gated · how lessons are made

Not signed in: your progress and quiz score won't be saved.
Progress1 / 9

Two clocks, and why

Rendering runs as fast as the machine allows. Physics does not. Unity steps the physics simulation on a fixed timestep, 0.02 seconds by default, which is 50 steps per second, set under Edit > Project Settings > Time > Fixed Timestep.

The reason is stability. A physics solver integrates forces over a time slice, and its accuracy depends on that slice being small and predictable. Feed it a variable frame time and identical situations resolve differently on different hardware: a stack of crates that settles on a desktop explodes on a phone that hitched for 200 milliseconds.

So Unity decouples them. However long the frame took, physics advances in uniform 0.02s bites. If a frame took 0.05s, the engine runs the step twice and carries the remainder. If a frame took 0.008s, physics may not step at all.

Everything else in this lesson follows from that one decision.

Full lesson text

All 9 steps on one page, for reading, reference, and search.

Show

1. Two clocks, and why

Rendering runs as fast as the machine allows. Physics does not. Unity steps the physics simulation on a fixed timestep, 0.02 seconds by default, which is 50 steps per second, set under Edit > Project Settings > Time > Fixed Timestep.

The reason is stability. A physics solver integrates forces over a time slice, and its accuracy depends on that slice being small and predictable. Feed it a variable frame time and identical situations resolve differently on different hardware: a stack of crates that settles on a desktop explodes on a phone that hitched for 200 milliseconds.

So Unity decouples them. However long the frame took, physics advances in uniform 0.02s bites. If a frame took 0.05s, the engine runs the step twice and carries the remainder. If a frame took 0.008s, physics may not step at all.

Everything else in this lesson follows from that one decision.

2. Rigidbody and Collider do different jobs

Two components, constantly confused.

  • A Collider is a shape: box, sphere, capsule, mesh. It defines what space is solid. On its own it is static geometry, walls and floors that never move.
  • A Rigidbody makes an object dynamic: it gains mass, gravity, velocity, and is moved by the solver.

Collider alone means immovable scenery. Collider plus Rigidbody means a thing that falls and gets pushed. Rigidbody with no Collider means it falls through everything, because nothing gives it a shape to collide with.

A collider marked Is Trigger stops being solid and becomes a detector: things pass through it and you get OnTriggerEnter instead of OnCollisionEnter. That is how checkpoints and pickup zones work.

One performance rule up front: never move a static collider. Unity optimizes on the assumption they hold still, and shifting one forces an expensive rebuild of its data. If it must move, give it a Rigidbody marked kinematic.

3. Move it with the solver, not around it

The most common physics bug: an object has a Rigidbody, and you move it by writing transform.position. That teleports it. It skips the solver entirely, so it passes through walls, arrives with no velocity, and produces no believable collision.

Once something has a Rigidbody, the Rigidbody owns its position.

private Rigidbody rb;
private Vector3 input;

private void Awake() => rb = GetComponent<Rigidbody>();

private void Update()        // read input on the frame clock
    => input = new Vector3(Input.GetAxis("Horizontal"), 0f, Input.GetAxis("Vertical"));

private void FixedUpdate()   // act on the physics clock
{
    rb.AddForce(input * 20f);            // accelerate
    // rb.MovePosition(rb.position + v); // kinematic-style, still swept
    // transform.position += v;          // WRONG: teleports past walls
}

Note the split: input is polled in Update because a key press lives for one frame, then applied in FixedUpdate because that is where physics listens. AddForce respects mass; MovePosition moves deliberately but still sweeps for collisions.

4. Interpolation: smooth at any frame rate

Physics updates 50 times a second. Your monitor may draw 144. So for most frames, the object has not moved since the last physics step, and you render it in a stale position. The result is subtle stutter, most visible on the object the camera follows.

The fix is one dropdown. Set the Rigidbody's Interpolate field:

  • None: render exactly where physics left it. Correct, and visibly steppy above 50fps.
  • Interpolate: smooth between the previous two physics positions. Smooth, at the cost of showing a position one physics step behind.
  • Extrapolate: predict ahead from current velocity. No lag, but it guesses, so it visibly overshoots on impacts.

The practical rule: turn Interpolate on for the player and anything the camera watches closely, and leave everything else on None. It costs nothing in gameplay terms, since it changes only what you draw, never what the solver computes. Enabling it on hundreds of objects is wasted work.

5. Tunneling and continuous collision detection

A bullet travelling 100 metres per second moves 2 metres per physics step. If the wall is 0.2m thick, the bullet is in front of it at one step and behind it at the next. The solver only tests at discrete moments, so it never saw a collision. The bullet passes through the wall. This is tunneling.

The Rigidbody's Collision Detection mode decides how hard the engine looks:

  • Discrete: test at each step's position. Cheapest, and tunnels on fast objects. The default.
  • Continuous: sweep the shape along its path against static colliders.
  • Continuous Dynamic: sweep against moving colliders too. Most expensive.
  • Continuous Speculative: cheaper sweeping approach, also works for rotation.

Set Continuous Dynamic on the fast object itself, not on everything in the level. Sweeping is real CPU work, and turning it on globally is a classic way to halve your frame rate for no benefit.

Cheap alternative for projectiles: skip Rigidbodies entirely and Physics.Raycast along the path each step.

6. Collision callbacks and layers

Contacts arrive as callbacks, fired after the solver has resolved the step, so the data describes an outcome, not a prediction.

private void OnCollisionEnter(Collision c)   // solid contact
{
    if (c.relativeVelocity.magnitude > 5f) PlayCrash();
    Debug.Log(c.contacts[0].point);
}

private void OnTriggerEnter(Collider other)  // passed through a trigger
{
    if (other.CompareTag("Player")) Collect();
}

OnCollisionEnter gives you a Collision with contact points and impact velocity. OnTriggerEnter gives you only the other Collider. Use CompareTag rather than other.tag == "Player", which allocates a string.

For a pair to report anything, at least one of them needs a Rigidbody. Two static colliders touching produce silence, which is a very common cause of "my trigger does not fire".

The scaling tool is the layer collision matrix (Project Settings > Physics). Untick pairs that can never interact and the engine stops testing them at all. Bullets that only ever hit enemies and walls should not be tested against every pickup in the level.

7. Where physics cost actually comes from

Physics gets blamed for frame drops it did not cause. The real costs are specific.

CostWhyFix
Mesh colliderstest against every triangleapproximate with box/capsule/sphere
Non-convex mesh colliderscannot be dynamic, very costlyconvex, or primitives
Continuous detection everywheresweeps every steponly on genuinely fast objects
Moving static collidersrebuilds acceleration structuresadd a kinematic Rigidbody
Everything collides with everythingquadratic pair testsprune the layer matrix
Timestep too smallmore steps per second0.02 is fine for most games

The timestep is a tempting dial and a dangerous one. Halving it to 0.01 doubles physics work per second. Worse, if a step takes longer than the timestep, the engine tries to catch up by running more steps, which takes longer still. That feedback loop is the death spiral, and Maximum Allowed Timestep exists to cap it: past that budget physics simply falls behind in slow motion rather than freezing the game.

8. When not to use physics at all

A rigidbody simulation is the right answer for tumbling debris, stacked crates, vehicles, and ragdolls. It is often the wrong answer for a player character.

Players expect precise, responsive, slightly unrealistic movement: instant stops, air control, no sliding on slopes. A Rigidbody gives you momentum and friction fighting exactly those expectations, which is why so much time is lost tuning drag to stop a character skating. Unity ships CharacterController for this: it sweeps and collides, but it is not simulated, so you move it directly and it does what you say.

The honest rule: use physics where emergent behavior is the point, and hand-authored motion where feel is the point. Many shipped games use a CharacterController for the player and Rigidbodies for everything they knock over.

And a determinism warning: Unity's physics is not deterministic across platforms or even reliably across runs. Never build lockstep multiplayer or replay systems on the assumption that it is.

9. How one frame drives physics

The engine accumulates elapsed time and spends it in fixed 0.02s steps, so a slow frame runs several and a fast frame may run none. Interpolation then decides what you actually see.

flowchart TD
  A["frame took N seconds"] --> B["add N to the accumulator"]
  B --> C["accumulator >= 0.02s?"]
  C --> D["yes: run FixedUpdate, solve, fire collision callbacks"]
  D --> E["subtract 0.02 and check again"]
  E --> C
  C --> F["no: physics is done for this frame"]
  F --> G["Update and LateUpdate run"]
  G --> H["Interpolate on? draw between last two physics positions"]
  H --> I["render"]

Check your understanding

The lesson ends with a 5-question quiz. Take it in the player above to see your score.

  1. Why does Unity run physics on a fixed 0.02s timestep instead of once per rendered frame?
    • To cap physics at 50 objects per scene
    • Because the GPU cannot render faster than 50fps
    • So the solver gets uniform time slices, making results stable and hardware-independent
    • To leave every other frame free for rendering
  2. An object has a Rigidbody and you move it with `transform.position += delta`. What goes wrong?
    • It teleports, skipping the solver, so it passes through walls with no collision
    • Nothing; this is the recommended way to move a Rigidbody
    • It moves at half speed because physics halves the delta
    • Unity throws a runtime exception
  3. A bullet moving 100 m/s passes straight through a thin wall. The targeted fix is:
    • Increase the bullet's mass
    • Set the bullet's Collision Detection to Continuous Dynamic
    • Turn on Interpolate for the bullet
    • Make the wall a trigger
  4. Your Rigidbody player looks slightly steppy at 144fps even though physics is fine. Best fix?
    • Lower Fixed Timestep to 0.005
    • Move the movement code into LateUpdate
    • Switch the player to a mesh collider
    • Set the Rigidbody's Interpolate to Interpolate
  5. Your trigger volume never fires OnTriggerEnter when a wall passes through it. Most likely cause?
    • Neither object has a Rigidbody, so the pair is never tested
    • Triggers only work in Update, not FixedUpdate
    • Trigger callbacks need the objects to share a tag
    • OnTriggerEnter only fires for objects with mesh colliders

Related lessons

AI
advanced

Finding the Next One: Fusion Beyond Attention

The pattern that made attention slow recurs across the stack, and once you know what to look for it is easy to find. This lesson applies the diagnosis to normalisation layers, optimizer steps, loss functions and inference decoding, covers why fused attention silently stops applying when a model deviates slightly from standard, and gives the profiling routine that decides where to look first.

10 steps·~15 min
AI
advanced

Writing Fused Kernels Without Writing CUDA

The reason most teams never fuse anything is that CUDA asks you to manage threads, shared memory and synchronisation by hand. Triton moves the unit of programming from a thread to a block and hands the rest to a compiler. This lesson covers what that buys, what it still asks of you, how to decide a kernel is worth writing, and how to be sure it is correct.

10 steps·~15 min
AI
advanced

Attention Is Memory-Bound, and Nobody Noticed for Five Years

For years attention was optimised by reducing FLOPs, and approximate methods that cut FLOPs kept failing to run faster. The reason is that attention was never compute-bound: it spends its time moving a matrix between GPU memory tiers. This lesson establishes that hierarchy, counts the traffic a standard implementation generates, and shows why an exact algorithm beat every approximation.

10 steps·~15 min
Programming
advanced

Scheduling and Resources: Requests Are Not Limits

Two numbers govern where a pod lands and how it behaves under pressure, and they do completely different jobs. Requests are used for placement and are a promise; limits are enforced at run time and are a ceiling. This lesson separates them, covers the asymmetry between CPU and memory enforcement, and explains what actually happens when a node runs out.

8 steps·~12 min