Skip to content

Scenes & prefabs

A scene is a JSON document (.vscn.json) describing a tree of entities plus environment settings. The Zod schemas in packages/engine/src/scene/schema/ are the single source of truth for the format — see the generated Scene Schema reference.

loadScene(url, ctx) fetches and parses a scene; loadSceneFromData(data, ctx) skips the fetch. Either way the loader runs three passes (packages/engine/src/scene/scene-loader.ts):

Three passes: 1 spawn entities and build id map, 2 create joints, 3 init components
The loader's three passes.
  1. Spawn. spawnEntity recurses into each entity’s children and registers every id (including nested ones) in an id → Object3D map.
  2. Joints. createSceneJoints links physics bodies together using that id map (a joint references its targets by id).
  3. Init. componentManager.initAll() runs every component’s init() — now that all entities and joints exist, so an init() can safely reference other entities.

loadScene returns a SceneInstance with an update(dt) to tick per frame and a dispose() to tear everything down.

packages/engine/src/scene/defaults.ts is the single source of default values shared by the editor and the runtime, so what you preview in the editor is what the game renders.

A prefab (.prefab.json) is a reusable entity template: { version, name, root }. A scene entity references one via a prefab field. When an entity has both a prefab and its own fields, mergePrefabInstance takes the prefab definition first, then applies the per-instance overrides on top. The merge is per-section: most sections (mesh, material, transform, …) are replaced by the instance when present, components are deep-merged, joints are replaced, and children are appended — so one prefab can have many customized instances. The loader caches fetched prefab and material files.

Helper queries walk the live tree:

  • queryByTag(root, tag)
  • queryByName(root, name)
  • queryByComponent(root, componentName)

Metadata (tags, components, the entity definition) is stored in each object’s userData.