Skip to content

Design philosophy

vgai’s design is shaped by one north star: it should be a great engine for an AI (or a human) to author games in. That yields three priorities.

There should be one obvious place and one obvious way to do a thing. The engine avoids configurable indirection in favor of a single, predictable path. The clearest expression of this is phase ordering.

Every fixed tick runs systems and GameComponent.update() methods in a fixed order:

#PhaseWhat runs
1inputSample keyboard / mouse / gamepad.
2prePhysicsApply forces/intents to rigid bodies.
3physicsStep the Rapier world.
4postPhysicsRead physics back; sync transforms to Object3D; dispatch triggers.
5gameLogicGeneral gameplay. Default phase for GameComponents.
6animationAdvance animation graphs / mixers.
7preRenderCamera/HUD fixups before drawing.
8renderDraw the frame.

A component declares its phase with a static field; data flows in one direction through the phases, so you never wonder “did this run before or after physics?”

A feature lives in one place. The scene format, the Zod schema that validates it, and the default values that the editor and runtime share are all single sources of truth in packages/engine/src/scene/. Change the schema once and the editor inspector, JSON-Schema autocomplete, and runtime validation all update together.

Bad data should fail loudly at load time, not silently at frame 10,000. Unknown component names throw when a scene loads; schema parsing rejects malformed fields. npm run validate-scenes checks every scene against the registry before you ship.

Because the editor edits the very Object3Ds the runtime uses, two things fall out for free:

  • Hot reload of behavior — swap a GameComponent’s code and keep its live state.
  • Editor-edits-truth — what you see in the editor is what the game runs.

UI is mounted with mountUI(ctx.uiContainer, <Component/>) and is for HUD/overlay only — not gameplay objects. The uiContainer is pointer-events-transparent by default; interactive elements opt back in. (The Visual UI Editor builds on this.)