Skip to content

Migration Guide

Migrating from 0.8.x to 0.9.x

SAGE 0.9.0 includes several breaking changes from the 0.8.x series. This guide walks through each change with before/after code examples.

1. Update Dependencies

SAGE now requires BabylonJS 9.0 and @babylonjs/loaders as a peer dependency:

bash
npm install @babylonjs/core@^9.0.0 @babylonjs/havok@^1.3.10 @babylonjs/loaders@^9.0.0

If you had import '@babylonjs/loaders/glTF' in your own code, remove it. SAGE now registers all loaders automatically via registerBuiltInLoaders().

2. Rename SkewedAspectGameEngine to GameEngine

typescript
// Before
import { SkewedAspectGameEngine } from '@skewedaspect/sage';

// After
import { GameEngine } from '@skewedaspect/sage';

3. Update Event Bus Usage

TypedEventBus was merged into GameEventBus:

typescript
// Before
import { TypedEventBus } from '@skewedaspect/sage';
const bus = new TypedEventBus<MyEvents>();

// After
import { GameEventBus } from '@skewedaspect/sage';
const bus = new GameEventBus<MyEvents>();

4. Update Behavior Definitions

Behaviors switched to array-based registration with constructor identification:

typescript
// Before (0.8.x)
const entity = entityManager.createEntity('player', {
    behaviors: {
        movement: new MovementBehavior(),
        combat: new CombatBehavior(),
    },
});

// After (0.9.x)
const entity = entityManager.createEntity('player', {
    behaviors: [ MovementBehavior, CombatBehavior ],
});

5. Update LevelContext Access

Level subclasses now access services through this.gameEngine instead of individual injected references:

typescript
// Before
class MyLevel extends Level
{
    async buildScene()
    {
        const scene = this.sceneEngine.createScene();
        await this.entityManager.createEntity('player', {});
    }
}

// After
class MyLevel extends Level
{
    async buildScene()
    {
        const scene = this.gameEngine.engines.sceneEngine.createScene();
        await this.gameEngine.managers.entityManager.createEntity('player', {});
    }
}

6. Update onNodeAttached Signature

The behavior lifecycle hook now receives gameEngine as a second parameter:

typescript
// Before
onNodeAttached(node : TransformNode) : void
{
    const scene = node.getScene();
}

// After
onNodeAttached(node : TransformNode, gameEngine : GameEngine) : void
{
    const scene = node.getScene();
    const physics = gameEngine.physics;
}

7. Rename ChannelState to ChannelInfo

typescript
// Before
import type { ChannelState } from '@skewedaspect/sage';

// After
import type { ChannelInfo } from '@skewedaspect/sage';

8. Update getBindingsForAction Calls

The parameter order changed to accommodate device type filtering:

typescript
// Before
const bindings = bindingManager.getBindingsForAction('jump', 'gameplay');

// After — insert undefined for deviceType
const bindings = bindingManager.getBindingsForAction('jump', undefined, 'gameplay');

// Or filter by device type
const kbBindings = bindingManager.getBindingsForAction('jump', 'keyboard', 'gameplay');

9. Replace SceneLoader Usage

If you used SceneLoader.ImportMeshAsync directly, switch to the module-level function:

typescript
// Before
import { SceneLoader } from '@babylonjs/core';
const result = await SceneLoader.ImportMeshAsync('', '/assets/', 'model.glb', scene);

// After
import { ImportMeshAsync } from '@babylonjs/core';
const result = await ImportMeshAsync('/assets/model.glb', scene);

New Features Available After Migration

Once you've completed the migration, you can optionally adopt these new features:

Released under the MIT License.