Time
Frame timing, pausing, and slow motion.
Time.DeltaTime
Seconds since the last frame, multiplied by TimeScale. This is what gameplay should use — it reads 0 while the game is paused, so pausing is free rather than something every script has to check.
Translation += m_Velocity * Time.DeltaTime;Time.UnscaledDeltaTime
Real seconds since the last frame, ignoring TimeScale. What UI, transitions and (by default) audio use, so they keep moving while the game is paused.
// A menu animation that still runs behind a paused game.
m_FadeAlpha += Time.UnscaledDeltaTime * 2f;Which one you want, in one line
If it should freeze when the player pauses, DeltaTime. If it shouldn't, UnscaledDeltaTime. A pause menu that animates with DeltaTime is frozen the moment it appears — which is the bug this pair exists to prevent.
Time.TimeScale
The speed of game time. 1 is normal, 0 is paused, 0.5 is half-speed slow motion, 2 is double speed. Read and write. Clamped to >= 0 — negative isn't a supported "rewind".
Time.TimeScale = 0f; // pause
Time.TimeScale = 0.3f; // bullet time
Time.TimeScale = 1f; // back to normalSetting it to 0 stops physics, animation and anything driven by DeltaTime. Pooled entities freeze with everything else. Audio keeps playing unless you stop it, and loading still completes — you can pause mid-load.
A bullet-time effect, done with unscaled time so it doesn't slow its own ramp:
private System.Collections.IEnumerator SlowMotion(float duration)
{
Time.TimeScale = 0.25f;
float t = 0;
while (t < duration)
{
t += Time.UnscaledDeltaTime;
yield return null;
}
Time.TimeScale = 1f;
}Always put it back
TimeScale is global and survives everything except you setting it again — including a scene load. A pause menu that sets it to 0 and is then closed by a scene change leaves the next scene frozen. Reset it wherever you leave the paused state, and consider resetting to 1 in a level manager's OnCreate as a safety net.
Time.FixedDeltaTime
The step size the physics accumulator advances by, in seconds. Defaults to 1/50. Read and write — raising the rate trades CPU cost for simulation accuracy, the same as in any engine that exposes it.
This is the fixedTs your OnFixedUpdate receives. See GameEntity.
Time.FixedDeltaTime = 1f / 60f; // finer simulation, more steps per secondTime.TimeSinceStartup
Unscaled, monotonic seconds since the process started. Not reset by TimeScale, a scene load, or a pause — so it's the right clock for a loading-screen timeout, or a cooldown that must keep counting through a pause menu.
if (Time.TimeSinceStartup - m_LastFired > m_Cooldown)
Fire();Time.FrameCount
Real frames rendered since the process started. Never paused. Handy for "do this every N frames" work and for correlating log lines.
if (Time.FrameCount % 30 == 0)
RefreshExpensiveThing();Scaled or unscaled, by system
| System | Follows TimeScale? |
|---|---|
OnUpdate's ts argument | Yes |
Physics and OnFixedUpdate | Yes |
| Animation | Yes |
| Particles | Yes |
| Object pools | Yes — pooled entities freeze with everything else |
Coroutine yield return <seconds> waits | Yes — see below |
| Scene loading | No — completes even while paused |
| Audio | No, by default |
| UI and transitions | No |
Coroutine waits freeze at TimeScale = 0
A coroutine's timed waits are counted down with the same scaled ts that OnUpdate receives, so yield return 1.5f never completes while the game is paused. That's right for gameplay and wrong for a pause menu's own animation — build those out of yield return null plus Time.UnscaledDeltaTime instead:
// Freezes when paused:
yield return 1.5f;
// Keeps running when paused:
float t = 0;
while (t < 1.5f) { t += Time.UnscaledDeltaTime; yield return null; }See also
- GameEntity —
OnFixedUpdateand the fixed clock - Scenes — loading while paused, and fade transitions
- Coroutines —
yield return <seconds>and which clock it uses - UI — pause menus