Use this pattern when a per-frame visual change should pause with a
GameClock. Typical case: NPC work animations that freeze when world time
pauses.
If the motion is presentation-only, prefer Godot _process delta instead.
Idle dressing, mood-bubble bob, and camera feel belong there. The shipped 2D
demo uses that split. Calendar Clock Speed and Engine Time Scale stay
as distinct knobs.
When to use this pattern
Prefer clock time for these cases.
- Stop at
clock.speed_multiplier = 0. - Speed up with calendar fast-forward.
- Represent a world actor, not UI polish.
When NOT to use this pattern
Prefer raw Godot delta for these cases.
- Cursor blink, button hover, and menu open/close.
- Cosmetic idle dressing that keeps playing while world time is paused.
- Camera follow, particles, and other presentation feel.
Ask if calendar pause should stop the motion. If yes, use the clock. If only engine or SceneTree pause should stop it, use delta.
Shipped demo split
This is the 2.0.2 demo SSOT.
World facts stay on GameClock:
- Time dial, calendar UI, and TOD presets.
- Directional light and lighting rig.
- Stone lanterns and TOD sprites.
- Berry bush
AgeComponent. - Weather
DateChangeRandomToggler. - Emote spawn via
DateChangeSpawner.
Presentation stays on Godot delta:
- Ninja idle flip (
_process). - OldMan walk (physics).
- Emote bob after spawn (
_process). - Demo cameras.
Recipe (optional)
Copy demo/scripts/calendar_time_examples/clock_driven_flipper_example.gd
into your project when you want the clock-driven pause contract.
Real-time inspector knob
@export var interval_real_seconds :float = 10.0Convert to game-seconds with delta_multiplier
_interval_game_seconds= interval_real_seconds* clock.time_scale.delta_multiplierExclude speed_multiplier when the host already scales the emitted
game_seconds_advanced amount. Including it would double-apply speed.
Advance from game_seconds_advanced
func _on_game_seconds_advanced(p_amount :float, _p_total :float)-> void:
if p_amount<= 0.0:
return
_elapsed_game_seconds+= p_amount
if _elapsed_game_seconds>= _interval_game_seconds:
_elapsed_game_seconds= fmod(_elapsed_game_seconds, _interval_game_seconds)
_flip()See also
- What Should Drive What? — beginner routing.
- Speed Stack and Clock Pacing — full speed composition.
- TimeScale & DriveMode — host ownership.