Skip to content

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.

csharp
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.

csharp
// 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".

csharp
Time.TimeScale = 0f;      // pause
Time.TimeScale = 0.3f;    // bullet time
Time.TimeScale = 1f;      // back to normal

Setting 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:

csharp
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.

csharp
Time.FixedDeltaTime = 1f / 60f;   // finer simulation, more steps per second

Time.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.

csharp
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.

csharp
if (Time.FrameCount % 30 == 0)
    RefreshExpensiveThing();

Scaled or unscaled, by system

SystemFollows TimeScale?
OnUpdate's ts argumentYes
Physics and OnFixedUpdateYes
AnimationYes
ParticlesYes
Object poolsYes — pooled entities freeze with everything else
Coroutine yield return <seconds> waitsYes — see below
Scene loadingNo — completes even while paused
AudioNo, by default
UI and transitionsNo

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:

csharp
// 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

  • GameEntityOnFixedUpdate and the fixed clock
  • Scenes — loading while paused, and fade transitions
  • Coroutinesyield return <seconds> and which clock it uses
  • UI — pause menus