Bullet Time
Slowing the world while the player keeps moving at full speed — two clocks, not one.
Examples
Captured from this page's own interactive demo below.
Overview
Bullet time slows everything except the player: enemies, projectiles, and VFX crawl while the player dodges and aims at normal speed — Max Payne's signature, and the moment slow motion stops being a global toggle and becomes a systems problem.
Global Time.timeScale can't express this: it slows everyone equally. The real technique gives objects local clocks — each consumer multiplies delta time by its own scale — so 'the world' runs at 0.2 while 'the player' runs at 1.0. Physics, animation speeds, particle systems, and audio pitch all have to respect the right clock, which is exactly why this is Advanced.
The payoff is a power fantasy no global slow-mo can deliver: the player isn't watching a slow world, they're fast in it. The contrast between the two speeds — visible in every crossing pair of objects — is the whole effect.
Interactive Demo
Use Cases
Best Practices
Do
- ✓Route every time consumer through a clock reference (world clock vs. player clock) instead of reading Time.deltaTime directly.
- ✓Ease the world scale in and out over ~100–200ms — an instant 1.0→0.2 step reads as a hitch, not an ability.
- ✓Drop the pitch of world-driven audio while it's slowed — the ear notices desynced sound faster than the eye notices motion.
Don't
- ✕Don't implement it with global timeScale plus a 'speed up the player to compensate' multiplier — animation, physics, and input latency all drift out of tune.
- ✕Don't let UI, camera smoothing, or input polling run on the world clock — the interface must stay on real time.
- ✕Don't leave world physics on the default fixed timestep unadjusted if the world clock drives Rigidbody motion — stutter appears exactly when everyone is staring.
Common Mistakes
- ⚠Missing one system (a particle burst, a tween, a footstep sound) that still runs on the global clock and instantly breaks the illusion.
- ⚠Restoring the world scale abruptly when the ability ends mid-dodge, teleporting every slowed projectile into full speed.
- ⚠Letting cooldown/ability timers tick on the world clock, so bullet time extends its own duration.
Implementation
Paste this into your AI assistant (Cursor, Copilot, Claude) to add the effect to your project.
Add the "Bullet Time" game-feel effect to my project: Slowing the world while the player keeps moving at full speed — two clocks, not one.
How it works: Bullet time slows everything except the player: enemies, projectiles, and VFX crawl while the player dodges and aims at normal speed — Max Payne's signature, and the moment slow motion stops being a global toggle and becomes a systems problem.
Guidelines:
- Route every time consumer through a clock reference (world clock vs. player clock) instead of reading Time.deltaTime directly.
- Ease the world scale in and out over ~100–200ms — an instant 1.0→0.2 step reads as a hitch, not an ability.
- Drop the pitch of world-driven audio while it's slowed — the ear notices desynced sound faster than the eye notices motion.
Avoid:
- Don't implement it with global timeScale plus a 'speed up the player to compensate' multiplier — animation, physics, and input latency all drift out of tune.
- Don't let UI, camera smoothing, or input polling run on the world clock — the interface must stay on real time.
- Don't leave world physics on the default fixed timestep unadjusted if the world clock drives Rigidbody motion — stutter appears exactly when everyone is staring.
Implement the effect in whatever engine/stack the project already uses and follow its existing code style. Wire it up where it makes sense.References
- Max Payne's bullet time — the trope codifier
- Game Feel — Steve Swink (book)
Comments
…