Skip to content

SceneTime

Defined in: SceneTime.ts:108

Per-scene time-effect arbitration: hitstop, slow motion / bullet time, freeze frames, and speed-ups that would corrupt each other if every caller wrote scene.timeScale directly (the “restore to what?” bug).

Resolved via the scene-scoped SceneTimeKey; the engine registers one instance per scene.

const time = this.use(SceneTimeKey);
time.freezeFor(0.08); // hitstop
const slow = time.scaleBy(0.25, { key: "slowmo" }); // bullet time
slow.release();

Composition: each key is a channel. Within a channel the latest active request wins (a newer request masks an older still-active one and reveals it again on expiry); across channels the winning factors multiply. A freeze is a ×0 factor, so it dominates arithmetically. scene.timeScale stays the game’s persistent speed knob — this service reads it as an input and never writes it: effectiveScale = scene.timeScale × Π(channel winners).

Request timers age on raw frame time, before any systems run, and only while the scene is active — a stack-paused scene holds its effects (note: that means pause-menu time does not consume a hitstop). Effects are transient: they release on scene exit and are not saved; games re-issue them after loading a snapshot.

new SceneTime(scene): SceneTime

Defined in: SceneTime.ts:121

Scene

SceneTime

get activeLabels(): readonly string[]

Defined in: SceneTime.ts:150

Display labels of all active requests, in creation order per channel.

readonly string[]


get effectiveScale(): number

Defined in: SceneTime.ts:130

The scale every non-excluded consumer runs at: scene.timeScale × Π(channel winners). Physics always steps under this full value (exclusions never apply to the shared world).

number


get elapsed(): number

Defined in: SceneTime.ts:140

Simulation seconds elapsed in this scene: raw frame time scaled by SceneTime.effectiveScale, accrued only while the scene is active. A stack-paused scene, a timeScale of 0, and an active freeze all hold it. Starts at 0 each time the scene is entered and is not saved.

number


get isFrozen(): boolean

Defined in: SceneTime.ts:145

True while SceneTime.effectiveScale is 0.

boolean

_releaseAll(): void

Defined in: SceneTime.ts:300

Internal

Release every request. Called by the engine on scene exit.

void


_tick(dt): void

Defined in: SceneTime.ts:264

Internal

Age request timers by raw frame time. Called by the engine at the start of earlyUpdate for each active scene, so a request created later in the frame is not aged until the next frame. Masked entries keep aging. Also prunes destroyed entities from exclusion sets.

number

void


effectiveScaleForUpdates(entity): number

Defined in: SceneTime.ts:164

The scale entity’s component updates, ProcessComponent, and particle emitters run at: like SceneTime.effectiveScale, but a channel whose winner excludes the entity contributes 1. entity.timeScale is not included — the update pipeline composes it on top.

Entity

number


freezeFor(duration, options?): TimeEffectHandle

Defined in: SceneTime.ts:199

Freeze the scene (a ×0 factor) for duration real-time seconds. Returns the same handle shape as scaleBy for an early release. Freezes are whole-scene by design — a shared physics world has no per-entity time, so freeze requests take no excludeUpdates.

number

SceneTimeFreezeOptions

TimeEffectHandle


scaleBy(factor, options?): TimeEffectHandle

Defined in: SceneTime.ts:174

Add a scale request. factor must be finite and > 0 (freezing goes through SceneTime.freezeFor); factors above 1 speed the scene up — physics catch-up is capped at ~8 sub-steps per frame.

number

SceneTimeScaleOptions

TimeEffectHandle