Scenes
How a Scene wraps an EntityComponentDataset into an isolated world, and how SceneManager creates scenes and switches the active one.
Scenes
A scene is a named world that owns its own EntityComponentDataset, so entities in one scene are fully isolated from another. Many scenes can exist at once, but only one is active — attached to the EntityManager — at a time. Switching scenes swaps the active dataset in a single step, which is how you move between, say, a menu and a level.
You rarely build scenes by hand. The engine’s SceneManager (at engine.sceneManager) creates them and switches between them:
const sm = engine.sceneManager;
sm.create("main"); // register an empty scene named "main"
sm.set("main"); // make it the active scene
create returns the Scene, so you can populate its dataset before activating it:
const level = sm.create("level-1");
new Entity()
.add(new Transform())
.build(level.dataset);
sm.set("level-1"); // its entities are now live
Once a scene is active, engine.entityManager.dataset is that scene’s dataset — add and query entities through it as usual.
SceneManager
| Method | Description |
|---|---|
create(name) | Creates an empty Scene, registers it, and returns it |
set(name) | Switches to the named scene (synchronous dataset swap) |
getByName(name) | Looks up a registered scene |
exists(name) | true if a scene with that name is registered |
add(scene) | Registers a pre-built Scene instance |
remove(name) | Unregisters a scene, deactivating it first if active |
stackPush(name) | Remembers the current scene, then switches |
stackPop() | Returns to the last stackPush-ed scene |
clear() | Detaches the current scene, leaving none active |
current_scene | The active Scene, or null |
set throws if the name isn’t registered, and is a no-op if that scene is already active.
Waiting for assets to load
set swaps datasets instantly, which is fine when everything is already in memory. When the incoming scene needs meshes or terrain tiles to load first, use transitionToScene — it shows a loading screen, waits for visible terrain and mesh assets, compiles materials, renders one warm-up frame, then resolves:
import { transitionToScene } from "@woosh/meep-engine/src/engine/scene/transitionToScene.js";
await transitionToScene({ scene: myScene, engine, tasks: [myLoadTask] });
Advanced: custom Scene subclasses
create hands you a plain Scene, which is all most projects need. For a scene with its own build or teardown logic, subclass Scene, override the hooks you need, and register the instance with sm.add(new MyScene()):
| Hook | When it runs |
|---|---|
setup(options, engine, success, failure) | Build the world; call success() when done |
handlePreActivation() / handlePostActivation() | Around the dataset being attached |
handlePreDeactivation() / handlePostDeactivation() | Around the dataset being detached |
teardown(engine, success, failure) | Release resources |
A Scene also exposes name, dataset, active (an ObservedBoolean), destroyed, speedModifiers (clock multipliers active with the scene), and clear() (empties the dataset).
Where to go next
- ECS overview — the conceptual model.
- Entities — building entities and holding
EntityReferencehandles. - Saving & loading — serializing a scene’s dataset and marking entities transient.