SceneManager (System)

The SceneManagerImpl singleton provides imperative scene navigation for use outside React components — in event handlers, network callbacks, or third-party libraries. It wraps the Zustand scene store, following the same pattern as InputManager and AudioManager.

tsx
import { getSceneManager } from "@carverjs/core/systems";

How It Works #

The singleton is a thin passthrough to the Zustand sceneStore. All state lives in the store — the singleton just provides a non-React API for accessing it.

The <SceneManager> component must be mounted inside <Game> for scene navigation to work. The imperative API is for code that runs outside the React tree.


API #

getSceneManager() #

Returns the singleton instance. Creates it on first call.

destroySceneManager() #

Resets the scene store and nulls the singleton. Called automatically when <SceneManager> unmounts.

tsx
const sm = getSceneManager();

sm.go("gameplay", { level: 1 });        // Clear stack, navigate
sm.push("pause");                        // Push overlay
sm.pop();                                // Pop, return to previous
sm.replace("level2", { score: 500 });    // Swap current scene

All navigation methods accept an optional TransitionConfig as the last argument:

tsx
sm.go("menu", undefined, { type: "fade", duration: 1 });

Query #

tsx
sm.getCurrent();       // "gameplay" | null
sm.getStack();         // ["menu", "gameplay"]
sm.isTransitioning();  // false

Shared Data #

tsx
sm.setShared("score", 100);
sm.getShared<number>("score"); // 100

Usage #

Most game code should use the useScene hook inside React components. The imperative API is for edge cases:

tsx
// In a WebSocket message handler
socket.onmessage = (event) => {
  const data = JSON.parse(event.data);
  if (data.type === "game_start") {
    getSceneManager().go("gameplay", data.config);
  }
};
tsx
// In a timer callback
setTimeout(() => {
  getSceneManager().go("gameover", { score: 42 });
}, 60000);

Type Definitions #

See Types for TransitionConfig and SceneStoreState.