@modoki/engine / index / SYSTEM_PRIORITY
Variable: SYSTEM_PRIORITY
constSYSTEM_PRIORITY:object
Well-known priority tiers for system ordering.
Type Declaration
ECS Core
ANIMATION
readonlyANIMATION:150=150
Keyframe animation playback — after game logic, before transform propagation (priority 150) so animated local transforms propagate the same frame.
AUDIO
readonlyAUDIO:250=250
Audio — presentation tier, AFTER transform propagation (priority 250) so spatial sources + listener read post-propagation world positions. ≥ TRANSFORM so it keeps running while the sim is paused (a presentation concern).
GAME
readonlyGAME:100=100
Game logic systems (priority 100-199)
INPUT
readonlyINPUT:50=50
Input sampling — after TIME, before GAME (priority 50). The app-pipeline inputSystem merges attached sources into the Input resource here, so GAME-priority systems read a fresh frame. Not registered in the headless harness (tests set Input directly).
LATE_UPDATE
readonlyLATE_UPDATE:185=185
Post-physics correction tier — the Unity-style "LateUpdate" (priority 185). Runs AFTER animation (150) + physics writeback (175) and BEFORE the final transform propagation (200), so a system here reads the ACTUAL post-step pose and its edits still compose into this frame's render/audio. < TRANSFORM, so it's gated with the sim (frozen when paused). The canonical home for procedural post-physics correction: surface-snapping (sling puck), IK/bone fixups after animation, camera follow, constraint solvers. CONTRACT: read fresh state via the Transform trait (local; for a ROOT entity local == world) or getWorldTransform3D(id) (composes a parented entity's world on-demand from the fresh local chain). Do NOT read the worldTransforms cache — at 185 it still holds the pre-physics (TRANSFORM_PREPASS 170) snapshot. To move a body, use setBodyTranslation3D (so next frame's physics continues from the corrected pose) AND set the Transform trait (so this frame's propagation reflects it).
MATERIAL
readonlyMATERIAL:260=260
Material parameter driving — presentation tier (priority 260), AFTER transform propagation and ≥ TRANSFORM so it keeps writing driven material params (uniforms via object userData) while the sim is paused/stopped, exactly like AUDIO. Runs in the ECS pipeline (before the separate RENDER_3D frame callback reads the values).
PHYSICS
readonlyPHYSICS:175=175
2D physics step — after game logic + animation set velocities / drive kinematic bodies (priority 175), before transform propagation so children follow the post-physics pose.
PROJECTION
readonlyPROJECTION:300=300
Projections / store sync — after all state changes (priority 300)
TIME
readonlyTIME:0=0
Time resource update — must run first (priority 0)
TRANSFORM
readonlyTRANSFORM:200=200
Transform propagation — after all transform changes (priority 200)
TRANSFORM_PREPASS
readonlyTRANSFORM_PREPASS:170=170
Pre-physics world-transform pass — after game + animation write local transforms, BEFORE physics (priority 170), so worldTransforms holds THIS-frame world matrices when physics seeds/poses bodies. Physics for a PARENTED body reads its world pose from this cache (and inverts on readback) rather than re-walking the parent chain per body. The same transformPropagationSystem also runs again post-physics (TRANSFORM) so rendering sees the solved poses — it's idempotent (rebuilds the map each call).