Time & Simulation
Fixed vs variable timestep, event queues, and determinism
System Overview
Fixed timestep updates simulation at constant intervals (e.g., 60 FPS), ensuring deterministic, frame-rate independent behavior. Variable timestep uses actual frame time, simpler but non-deterministic and frame-rate dependent.
The accumulator pattern allows fixed timestep to handle variable frame rates: accumulate frame time, update in fixed steps until accumulator is depleted. This maintains determinism while adapting to performance variations.
Why Include Gravity?
Gravity (acceleration) is included in this demo for several important reasons:
- Amplifies Timestep Differences: Acceleration compounds over time. Small differences in timestep lead to larger position differences, making the fixed vs variable timestep divergence more visible and dramatic.
- Real-World Relevance: Most games use gravity for physics simulation. This demo shows how timestep choice affects real game scenarios, not just theoretical examples.
- Demonstrates Accumulation Error: With constant velocity, timestep differences are linear. With acceleration, errors accumulate quadratically, showing why fixed timestep matters for physics accuracy.
- Visual Clarity: The desync visualization (connecting lines and heatmap) becomes more meaningful when particles diverge significantly. Gravity ensures visible divergence occurs quickly.
- Performance Impact: Variable timestep with gravity can cause "spiral of death" - slow frames cause larger timesteps, which make physics more expensive, causing even slower frames. Fixed timestep prevents this.
Try it yourself: Set gravity to 0 and watch how the desync becomes minimal. Then increase gravity and observe how quickly the two simulations diverge. This demonstrates why fixed timestep is essential for physics-heavy games.
Why Games Use This
- Determinism: Fixed timestep ensures same result every time
- Replay/Networking: Deterministic simulation enables perfect replays
- Frame Independence: Physics work correctly at any FPS
- Stability: Fixed timestep prevents numerical instability
- Debugging: Reproducible behavior makes bugs easier to find
Key Parameters
- Fixed Timestep: Update interval (typically 1/60s = 16.67ms)
- Accumulator: Stores leftover time between frames
- Gravity: Force applied each timestep
- Bounce Damping: Energy loss on collision
Failure Modes
- Spiral of Death: Slow frames cause multiple updates, making it slower
- Desync: Variable timestep causes different results on different machines
- Too small timestep: Many updates per frame, performance issues
- Too large timestep: Physics becomes unstable, objects tunnel through walls
- Mixed timesteps: Some systems fixed, others variable causes desync
Scaling Behavior
Fixed timestep performance depends on update frequency and complexity. If frame time exceeds timestep, multiple updates occur per frame. Worst case: frame takes longer than timestep, causing spiral of death.
Variable timestep is O(1) per frame but non-deterministic. Fixed timestep is O(n) where n = frame_time / timestep.
Related Algorithms
- Substepping: Multiple physics steps per frame
- Interpolation: Smooth rendering between fixed updates
- Event Queues: Time-sorted events for discrete simulation
- Time Dilation: Slow motion effects
- Time Rewind: Deterministic replay for undo/rewind
Free Tools & Libraries
- Box2D: Physics engine with fixed timestep
- Unity: Built-in fixed timestep support
System-Thinking Prompts
- What happens when frame time > timestep? Spiral of death?
- Where does determinism break? Floating point errors, variable timestep?
- How do different frame rates affect simulation? 30 FPS vs 144 FPS?
- Which parameter dominates? Timestep size or update complexity?
- What's the optimal timestep? Too small vs too large?
- How does desync accumulate? Over seconds, minutes, hours?
- Can we guarantee determinism? Or is approximate acceptable?