Lifecycle
Mental model: lifecycle is about when the ECS does what. Understand boot, system setup, per‑frame execution, and teardown.
World lifecycle and boot sequence
When you call World.create(container, options) IWSDK:
- Constructs a
Worldinstance and registers core components/systems:Transform,Visibility,TransformSystem,VisibilitySystem. - Creates Three.js objects:
Scene,PerspectiveCamera,WebGLRenderer; enables WebXR. - Wraps the Scene in an entity (
world.sceneEntity) and initializes anactiveLevelentity beneath it. - Sets up default lighting unless disabled (gradient environment + background).
- Creates
XRInputManager; wiresplayer(XROrigin) andinputinto the world. - Registers core feature systems (always‑on UI, Audio; optional Locomotion/Grabbing) with explicit priorities.
- Initializes
AssetManager. - Starts the render loop (
renderer.setAnimationLoop): each tick setsvisibilityState, runsworld.update(delta, time), then renders. - If
options.xr.offeris 'once' or 'always', IWSDK offers an XR session after init (and re‑offers on end if 'always'). Otherwise, callworld.launchXR()manually when the user presses your XR button. - Preloads assets (if provided) and requests an initial level load via
world.loadLevel(url?).
Implications
- Systems run on every animation frame in priority order before the scene is rendered.
- Default priorities (negative numbers run earlier): Locomotion (−5), Input (−4), Grabbing (−3). You can pass
{ priority: number }when registering a system. visibilityStateis updated each frame from the XR session (ornon-immersive).
System lifecycle (per class)
init()- Subscribe to query
qualify/disqualifyevents. - Set up configs (
this.config.foo.subscribe(...)). - Wire DOM/renderer listeners; enqueue cleanups into
this.cleanupFuncsif you create disposables.
- Subscribe to query
update(delta, time)- Iterate your query sets. Use
for (const e of this.queries.name.entities). - Use
.peek()when reading config signals inside tight loops to avoid unnecessary reactivity. - Avoid allocations and nested loops in hot paths.
- Iterate your query sets. Use
destroy()- Dispose resources and undo listeners. IWSDK calls all
cleanupFuncsfor you.
- Dispose resources and undo listeners. IWSDK calls all
Query membership and when it changes
- Adding/removing a component on an entity (
addComponent/removeComponent) triggers query re‑evaluation for component presence. - Changing a component value with
setValuetriggers re‑evaluation for queries whosewhere:predicates depend on that component. getVectorViewreturns a typed slice; mutating it does NOT trigger re‑evaluation on its own. If a query depends on that field, write back viasetValueor mirror a scalar used in predicates.- Subscribe to membership edges:
ts
this.queries.panels.subscribe('qualify', (e) => {
/* attach once */
});
this.queries.panels.subscribe('disqualify', (e) => {
/* cleanup */
});Entity lifecycle
createEntity()creates a bare entity (noobject3D).createTransformEntity(object?, parentOrOptions?)creates an entity with anobject3D, injects aTransform, and parents it under the level root or scene based on options.entity.destroy()marks the entity inactive, clears its bitmask, resets query membership, and detaches itsobject3Dfrom the scene.
Parenting rules
- If you pass
{ parent: Entity }, the resultingobject3Dis added under the parent’sobject3D. { persistent: true }forces parenting under the scene (survives level swaps).- Otherwise, entities created during a level load are parented under the active level root; persistent utilities under the scene.
Frame order recap
text
set visibilityState → world.update(delta,time) → renderer.render(scene,camera)Within world.update, systems run in ascending priority (more negative first). Use lower (more negative) priorities for input/physics that must run before visuals.
Frame diagram (text)
text
requestAnimationFrame / XRAnimationFrame
└─ compute delta,time
├─ world.visibilityState ← session.visibilityState
├─ world.update(delta,time)
│ ├─ systems @ priority … -5, -4, -3, 0, 1 …
│ └─ queries keep sets up to date (qualify/disqualify emitted)
└─ renderer.render(scene,camera)