![Delta time]()
When developing games in Unity, one of the fundamental challenges is making movement, animations, and physics behave consistently across devices with varying frame rates. What runs smoothly at 60 FPS on a high-end PC may stutter or lag on a slower machine or one that temporarily exceeds 120 FPS. Unity’s Time.deltaTime is the go-to solution for this: it provides the precise duration (in seconds) of the last rendered frame, enabling you to scale any per-frame operation so it behaves the same regardless of frame rate.
Why does Frame-Rate Independence matter?
- Consistency Across Devices: Without frame-rate compensation, movement speeds and animations are tied directly to the rate at which frames are rendered. At 30 FPS, a character moving 1 unit per frame travels 30 units/sec; at 60 FPS, that same code yields 60 units/sec twice as fast!
- Gameplay Fairness: In multiplayer or competitive games, a faster machine shouldn’t gain an “unfair” speed boost or smoother input response merely by rendering more frames.
- Predictable Physics & Animations: Even in single-player titles, you want movement, timers, and effects to feel stable whether the game dips in performance or spikes above 60 FPS.
What is Time.deltaTime?
Time.deltaTime is a float representing the time, in seconds, since the last frame was rendered. For example, if your game is running at a constant 60 FPS, Time.deltaTime will be approximately 0.01667 seconds (1/60). If it dips to 30 FPS, deltaTime jumps to ≈ 0.03333 seconds.
Key point: Always multiply any per-frame change (movement, rotation, scaling, timers) by Time.deltaTime to convert it into a per-second change.
void Update()
{
float speed = 5f; // Units per second
float moveAmount = speed * Time.deltaTime;
transform.Translate(moveAmount, 0, 0);
}
Without that multiplication, Translate(5, 0, 0) would move 5 units every frame rather than per second.
Update() vs. FixedUpdate()
1. Update()
- Called once per frame.
- Use for input and frame-dependent logic.
- Multiply by Time.deltaTime.
2. FixedUpdate()
Common Use-Cases
Smooth Movement
void Update()
{
Vector3 direction = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
float moveSpeed = 3f;
controller.Move(direction * moveSpeed * Time.deltaTime);
}
Rotations & Smooth Look
void Update()
{
float yaw = Input.GetAxis("Mouse X") * 200f * Time.deltaTime;
float pitch = -Input.GetAxis("Mouse Y") * 200f * Time.deltaTime;
transform.Rotate(pitch, yaw, 0);
}
Timers & Cooldowns
private float cooldown = 5f;
private float timer;
void Update()
{
timer += Time.deltaTime;
if (timer >= cooldown)
{
FireProjectile();
timer = 0f;
}
}
Unscaled & Smoothed Variants
Pitfalls & Gotchas
Time Scale Side-Effects: If you pause the game by setting Time.timeScale = 0, deltaTime becomes 0. Any movement or timers in Update() will freeze. Use unscaledDeltaTime for any UI animations or effects you want to continue despite pause.
Best Practices
- Always think in “units per second”: Define speeds, rotations, or rates in per-second terms, then multiply by deltaTime.
- Separate input → logic → physics: Read inputs in Update(), apply physics in FixedUpdate(), each with the correct delta.
- Clap large deltas: Safeguard against spiraling updates when frame rates plunge.
- Use unscaled time where appropriate: UI elements and countdowns, which you still want to display during slow motion or pause.
- Profile on target hardware: Test on slow and fast devices. Observe deltaTime fluctuations in the Profiler to catch unexpected spikes.
Conclusion
Time.deltaTime is the cornerstone of frame-rate-independent game logic in Unity. By converting per-frame changes into per-second rates, you ensure consistent behavior across unsteady frame rates and varied hardware. Mastering deltaTime, along with its cousins fixedDeltaTime, unscaledDeltaTime, and smoothDeltaTime, is essential for smooth movement, fair gameplay, and predictable physics in any Unity project.