World
Reference documentation for the ECS World lifecycle, plugins, scenes, and resources.
Creating a World
Section titled “Creating a World”import { World } from '@shell/ecs';
const world = new World();Set the world’s immutable fixed timestep at construction. The value is in milliseconds and defaults
to 1000 / 60:
const world = new World({ fixedTimestepMs: 1000 / 120 });The root world owns the timestep for its complete lifetime. Child worlds inherit it; attempting to construct a child with a conflicting value throws.
World lifecycle
Section titled “World lifecycle”// Register components and pluginsworld.registerComponent(Transform, Velocity);world.addPlugin(MyPlugin);
// Mount starts the lifecycle: startup systems run, ticker startsawait world.mount();
// Pause/resumeawait world.pause();await world.continue();
// Unmountawait world.unmount(); // reloadable unloadawait world.unmount(false); // just stop (no unload)
// Permanently release world-owned stateawait world.dispose();Lifecycle methods
Section titled “Lifecycle methods”| Method | Description |
|---|---|
mount(mountToParent?) | Prepare systems, start ticker, and run lifecycle. Returns Promise<void>. For child scenes, mountToParent attaches to parent lifecycle. |
pause() | Sleep the lifecycle. Returns Promise<void>. |
continue() | Resume the lifecycle. Returns Promise<void>. |
unmount(reset?) | true (default) = full unload; false = just stop. Returns Promise<void>. |
isMounted() | Returns whether the world is currently mounted. |
clear() | Remove all entities, destroy systems and observers, and reset prepared state. Returns Promise<void>. |
dispose() | Permanently unload and release world-owned registrations and resources. Returns Promise<void>. |
Transition ordering and failures
Section titled “Transition ordering and failures”Lifecycle calls execute in invocation order and cannot interleave phases. Adjacent identical transitions share one promise while in flight. Lifecycle state advances only after every callback for the current phase succeeds, so a failed startup leaves the world unmounted and a failed unload retains the previous successful step. Both operations can be retried. Callback side effects that completed before a failure are not rolled back.
Pausing child scenes
Section titled “Pausing child scenes”The root world’s pause() stops its ticker. Child scenes share that ticker, so pausing a child instead
deactivates only the child’s scheduler owner. Its systems and observers stop executing while root and
sibling execution continues. continue() reactivates the owner. unmount(false) similarly
deactivates child execution without discarding definitions.
Permanent disposal
Section titled “Permanent disposal”unmount() is reloadable; dispose() is permanent. Disposal unregisters the world’s systems and
observers, removes scheduler hooks and owner activation, releases lifecycle subscriptions, disposes
its entity registry, and disposes only resources owned by that world. A child never disposes inherited
parent resources. Repeated disposal is safe, but a disposed world cannot be mounted or configured
again.
Registering components and systems
Section titled “Registering components and systems”// Pre-register components (useful for editors or deserialization)world.registerComponent(Transform, Velocity);
// Use each system's builder schedule (or Update by default)world.registerSystem(MoveSystem);world.registerSystem(SystemA, SystemB);
// Explicit schedules override builder schedulesworld.registerSystem(Schedule.Update, [SystemA, SystemB]);
// Unregister a systemworld.unregisterSystem(MoveSystem);
// Register runtime-required componentsworld.registerRequiredComponents(Transform, Position, PreviousPosition);Scenes
Section titled “Scenes”Scenes are child worlds that inherit resources from a parent.
// Define a sceneconst BattleScene = Define.scene('battle').build((world) => { world.registerSystem(Schedule.Update, BattleSystem);});
// Create from parent worldconst sceneWorld = world.createScene(BattleScene);const sceneWorld2 = world.createScene('empty-scene');
// Access via scene managerconst scenes = world.get('scenes');const battle = scenes.getScene('battle');
// Mount (registers lifecycle with parent)await sceneWorld.mount();Scene manager transitions are also asynchronous and resolve after teardown or startup completes:
| Method | Return type |
|---|---|
scenes.mount(name) | Promise<void> |
scenes.unmount(name) | Promise<boolean> (false when missing or inactive) |
scenes.goto(name) | Promise<void> |
scenes.deactivateAll() | Promise<void> |
scenes.clear() | Promise<void> |
Scene-manager transitions are serialized. A pending mount can be cancelled with either
scene.unmount() or scenes.unmount(name). Failed and unvisited pending scenes remain available for
retry. goto() unmounts the previous active set and attempts to restore it if the target mount fails;
an AggregateError reports a transition whose rollback also failed.
scenes.deactivateAll() performs reloadable unmounts. scenes.clear() permanently disposes every
child scene and releases its scheduler, observer, lifecycle, entity-registry, and resource ownership.
Inheritance model
Section titled “Inheritance model”- Inherited (shared): components, scheduler, ticker, queries, archetypes, events, mutationHooks
- Isolated (per-scene): entities, systems, commands, lifecycle, observer registrations
- Startup systems stay with their owning world by default. A
.forEachWorld()builder clone registered on a startup schedule creates a fresh instance for its owner and every descendant lifecycle. - Observer dispatch is shared, but each observer runs with and is destroyed by its owning world.
- Optional isolated (manually bound): serializer
IoC container and resources
Section titled “IoC container and resources”The World uses dependency injection for resource management.
Binding resources
Section titled “Binding resources”// Class binding (lazy singleton — instantiated on first .get())world.bindResource('myService', MyServiceClass);
// Factory bindingworld.bindResource('factory', (container) => new X(container.get('dep')));
// Instance binding (immediate)world.bindResource('config', { debug: true });Accessing resources
Section titled “Accessing resources”world.get('myService'); // from Worldresources.get('scheduler'); // from system update paramsType safety via module augmentation
Section titled “Type safety via module augmentation”declare module '@shell/ecs' { interface IocRegistry { myService: MyServiceClass; }}Built-in resources
Section titled “Built-in resources”| Key | Type | Description |
|---|---|---|
scheduler | Scheduler | Tick loop, system execution |
commands | Commands | Entity operations |
events | Events | Event system |
entities | Entities | Entity count, iteration |
components | Components | Component registry |
queries | QueryRegistry | Query creation |
archetypes | Archetypes | Archetype management |
scenes | SceneManager | Child world registry |
ticker | Ticker | Frame loop (root world only) |
lifecycle | LifeCycle | Mount/start/stop/unload |
mutationHooks | MutationHooks | Entity/component change callbacks |
Optional (manually bound, from @shell/serialization):
| Key | Type | Description |
|---|---|---|
serializer | SceneSerializer | Save/load/apply |
Utility
Section titled “Utility”| Method | Description |
|---|---|
world.toString() | Returns Shell ECS - version <VERSION> |
world.uid | Unique identifier for the world instance |
world.isRoot() | Returns true if this world has no parent |
world.inherit() | Creates a new child world inheriting from this one |