ECS 101
Updated: Sep 4, 2026
IWSDK uses the elics entity-component-system runtime. Components hold typed data, systems implement behavior, and queries maintain live sets of matching entities.
- An entity is an identity that owns components.
- A component is a data schema without behavior.
- A system runs behavior over one or more queries.
- A query updates as entities gain, lose, or change relevant components.
- The World owns the ECS scheduler, scene, renderer, assets, input, and XR session.
Components describe state
↓
Queries select entities
↓
Systems update behavior
↓
World renders the result
Create a component and system
This regeneration system updates each entity that has Health.
import { Types, World, createComponent, createSystem } from '@iwsdk/core';
const Health = createComponent('Health', {
current: { type: Types.Float32, default: 100 },
max: { type: Types.Float32, default: 100 },
});
class HealthRegenSystem extends createSystem(
{ targets: { required: [Health] } },
{ perSecond: { type: Types.Float32, default: 5 } },
) {
update(delta: number) {
for (const entity of this.queries.targets.entities) {
const current = entity.getValue(Health, 'current')!;
const maximum = entity.getValue(Health, 'max')!;
entity.setValue(
Health,
'current',
Math.min(maximum, current + delta * this.config.perSecond.peek()),
);
}
}
}
const world = await World.create(document.getElementById('scene')!);
world.registerComponent(Health);
world.registerSystem(HealthRegenSystem);
const player = world.createEntity();
player.addComponent(Health, { current: 25, max: 100 });
Connect an entity to Three.js
Use createTransformEntity() when an entity needs a Three.js object and transform data.
import { BoxGeometry, Mesh, MeshStandardMaterial } from '@iwsdk/core';
const mesh = new Mesh(
new BoxGeometry(1, 1, 1),
new MeshStandardMaterial({ color: 0x4f7cff }),
);
const levelObject = world.createTransformEntity(mesh);
const persistentObject = world.createTransformEntity(undefined, {
persistent: true,
});
The first entity belongs to the active level. The persistent entity belongs to the scene root and survives level changes.
Feature names are singular configuration keys. Native scene files use .iwsdk.scene.json or .scene.json.
import { SessionMode, World } from '@iwsdk/core';
const world = await World.create(document.getElementById('scene')!, {
xr: { sessionMode: SessionMode.ImmersiveVR },
features: {
locomotion: true,
grabbing: true,
},
level: '/scenes/main.iwsdk.scene.json',
});
Load a scene from a URL or pass a parsed native scene document.
await world.loadLevel('/scenes/gallery.iwsdk.scene.json');
await world.loadSceneDocument(sceneDocument);
Both runtime APIs require an import-free scene. Use scene_flatten_file on an
authoring composition before loading the resulting file or document.
Both methods resolve after LevelSystem completes the requested load and updates the active level.