Skip to content

Scenes

A scene is a collection of entities, components, and parent-child relationships. You create scenes visually in the ESEngine editor, and they are saved as JSON files. At runtime, the engine loads the scene and spawns all entities with their configured components.

Scene Structure

A scene file contains:

  • Entities — each with a unique ID and a name
  • Components — data attached to each entity (transforms, sprites, colliders, etc.)
  • Hierarchy — parent-child relationships between entities
{
"version": "1.0",
"name": "Level1",
"entities": [
{
"id": 1,
"name": "Player",
"parent": null,
"children": [2],
"components": [
{ "type": "LocalTransform", "data": { "position": { "x": 0, "y": 0, "z": 0 } } },
{ "type": "Sprite", "data": { "texture": "player.png", "size": { "x": 32, "y": 32 } } }
]
}
]
}

Loading Scenes

In the editor, scenes are loaded automatically — you only write scripts that define components and systems.

After building your project, the engine automatically loads the scene, resolves all referenced assets (textures, materials, Spine), and creates a default camera if none exists. You don’t need to handle scene loading manually.

Finding Entities

By Name

Every entity loaded from a scene receives a built-in Name component with the name assigned in the editor. Query Name to find entities:

import { defineSystem, addStartupSystem, Query, Name, LocalTransform } from 'esengine';
addStartupSystem(defineSystem(
[Query(Name, LocalTransform)],
(query) => {
for (const [entity, name, transform] of query) {
if (name.value === 'Player') {
// found the player entity
}
}
}
));

By Component or Tag

Use a Query to find entities by their components:

import { defineSystem, addSystem, defineTag, Query, Mut, LocalTransform } from 'esengine';
const Player = defineTag('Player');
addSystem(defineSystem(
[Query(Mut(LocalTransform), Player)],
(query) => {
for (const [entity, transform] of query) {
// process each player
}
}
));

Traversing the Hierarchy

Use the Children component to walk the entity tree:

import { defineSystem, addSystem, Query, Children, LocalTransform } from 'esengine';
addSystem(defineSystem(
[Query(Children, LocalTransform)],
(query) => {
for (const [entity, children, transform] of query) {
// children.entities contains child entity IDs
}
}
));

Entity Hierarchy

Scene entities can form a tree via parent-child relationships. Set up parent-child relationships in the editor — the engine manages Parent and Children components automatically.

When a parent’s LocalTransform changes, the engine propagates the transform to all descendants via the WorldTransform component.

Dynamic Entities

You can spawn and despawn entities at runtime using Commands:

import { defineSystem, addSystem, Commands, LocalTransform, Sprite } from 'esengine';
addSystem(defineSystem(
[Commands],
(commands) => {
// Spawn a new entity with components
commands.spawn()
.insert(LocalTransform, { position: { x: 100, y: 0, z: 0 }, rotation: { w: 1, x: 0, y: 0, z: 0 }, scale: { x: 1, y: 1, z: 1 } })
.insert(Sprite, { texture: bulletTexture, color: { r: 1, g: 1, b: 1, a: 1 }, size: { x: 8, y: 8 } });
// Despawn an entity
commands.despawn(entity);
}
));

Scene Data Types

TypeFields
SceneDataversion: string, name: string, entities: SceneEntityData[], textureMetadata?: Record<string, TextureMetadata>
SceneEntityDataid: number, name: string, parent: number | null, children: number[], components: SceneComponentData[]
SceneComponentDatatype: string, data: Record<string, unknown>