Core loop
Usage guide of the loop every game runs on: the three clocks (game tick, physics step, render), the tick of each genre, render and physics Workers on the web, the engines (_process / Update / TickComponent, never _physics_process / FixedUpdate for logic), and the checks that fail a game or kit (gripforge game-check --loop, gripforge_core_loop_check, kit build, gripforge_game_audit) with their fixes.
The core loop of your game #
Every GripForge game, on every engine, runs on the same loop. The CLI, the MCP and the hosted creation apply it to each new game and fail a game or a kit that breaks it. The full contract: gripforge docs game-engine-contract, §12.
Three clocks #
| Clock | Rate | What runs there |
|---|---|---|
| Game tick | game.engine tick.hz (5..120 Hz) | All game logic: state, actions, timers, rules (kit update / late_update, hooks, triggers) |
| Physics step | its own fixed step (1/60 s) | Physics only: forces, velocities, contacts |
| Render | the display rate | Drawing; poses interpolated between the last two tick snapshots (alpha) |
Frame / present hooks and physics callbacks only read the published state. A heavy system runs every N ticks (kx.schedule, tick.systems), never through a throttle written by hand. The tick can change during play: runtime.core.tickAdjust({ hz }), the config, or the F3 panel.
The tick of your genre #
A new game gets its tick explicitly at creation:
| Kind of game | tick.hz |
|---|---|
| cards, collection (turn-paced) | 10 |
| strategy, tactics | 15 |
| tower defense | 20 |
| action (default) | 30 |
| racing, fighting, twitch shooters, physics sports | 60 |
Change it to your game's own pace: gripforge_gamekit_configure { id: "game.engine", config: { tick: { hz: 20 } } }.
Threads on the web #
Rendering runs in a Worker (OffscreenCanvas) and physics in its own Worker by default, when the page is cross-origin isolated (shared memory). Otherwise they fall back to the main thread and the reason is shown. No thread waits on another: each publishes its latest state (double buffer + seq), commands go through queues.
Engines #
The GripForge host steps the tick from the frame callback with the real frame time: Godot _process, Unity Update, Unreal TickComponent. Never run game logic in _physics_process, FixedUpdate or an async physics tick, and never change the engine's physics step (physics_ticks_per_second, Time.fixedDeltaTime): the pace of the game is tick.hz. Read the tick with tick_info() / TickInfo() and tick_alpha() / TickAlpha().
Check your game or kit #
gripforge game-check --loop ./my-game # the core loop rule alone, on every source and game document
gripforge game-check ./my-game # the production check, core loop included
gripforge kit build ./my-kit # refuses a kit that breaks the rule, before compiling
MCP: gripforge_core_loop_check { path } (local), gripforge_game_audit (a missing tick, fixed for free with fix: true).
| Rule | Fails when | Fix |
|---|---|---|
tick_missing | game.engine has no tick.hz | Set the tick of your genre |
frame_mutates_state | a frame / present hook or a requestAnimationFrame callback writes the game state | Move the write to the tick; the frame reads and interpolates |
physics_runs_gameplay | gameplay, or the GripForge tick, runs from a physics callback | Keep the physics callback for physics; rules run on the tick |
engine_physics_retuned | the engine physics step is changed | Leave it; change tick.hz |
worker_disabled | playerWorker=0 in a game (a URL/localStorage debug option ?worker.render=0 is fine) | Remove it, or state the reason |
shared_memory_disabled | memory.shared: false | Remove it, or state the reason |
physics_main_thread | physics placed on main, or placement: false | Remove it, or state the reason |
sync_worker_call | a tick path waits (Atomics.wait, synchronous call, await, block_on, .Wait(), .Result) | Post a command; read the latest published state next tick |
A switch you really need passes with its reason: a core-loop-reason: … comment on the line (or the line above), or "coreLoopReasons": { "worker_disabled": "…" } in the game document.