Develop

World

Updated: Sep 4, 2026
The World coordinates the ECS runtime, Three.js scene and renderer, input, player rig, assets, native scene loading, and WebXR session lifecycle.

Create a World

World.create(container, options) returns a promise for the initialized World.
import { SessionMode, World } from '@iwsdk/core';

const world = await World.create(document.getElementById('scene')!, {
  xr: {
    sessionMode: SessionMode.ImmersiveVR,
    offer: 'once',
  },
  features: {
    locomotion: true,
    grabbing: true,
  },
  level: '/scenes/main.iwsdk.scene.json',
});
features.locomotion and features.grabbing each accept true or their supported configuration object. They are disabled when omitted.

Scene and level roots

  • world.getActiveRoot() returns the current level root, or the scene root before a level is active.
  • world.getPersistentRoot() returns the scene root.
Entities created without a persistent option belong to the active level. Use { persistent: true } for objects that must survive a level change.
const levelEntity = world.createTransformEntity(mesh);
const persistentEntity = world.createTransformEntity(undefined, {
  persistent: true,
});

Create entities and register behavior

const dataEntity = world.createEntity();
const transformEntity = world.createTransformEntity(object3D);

world.registerComponent(Health);
world.registerSystem(HealthSystem, { priority: 0 });
createEntity() creates a bare ECS entity. createTransformEntity() adds a Three.js object and the intrinsic Transform component.

Load native scenes

loadLevel() accepts native .iwsdk.scene.json and .scene.json URLs.
await world.loadLevel('/scenes/gallery.iwsdk.scene.json');
Use loadSceneDocument() for an in-memory scene document.
await world.loadSceneDocument(sceneDocument);
Both methods require an import-free runtime scene. Use scene_flatten_file to flatten an authoring composition before loading the output.
Both methods return Promise<void> and resolve after the level request completes.

Control XR sessions

world.launchXR();

// Later:
world.exitXR();
launchXR(overrides?) requests a session using the creation options plus optional per-launch overrides. exitXR() ends the active session.
world.visibilityState is a signal whose values are non-immersive, hidden, visible, and visible-blurred.

Access a live XR frame

Register a callback only for work that requires XRFrame.
const unsubscribe = world.onXRFrame((frame, delta, time) => {
  readFrameData(frame, delta, time);
});

unsubscribe();
The callback runs during immersive XR after ECS systems and before rendering. Normal application logic belongs in a system.

Frame order

visibility state → world.update(delta, time) → XR-frame callbacks → render
See ECS lifecycle for initialization and cleanup details.