Quick Start
This guide will help you get started with ECS Framework, from installation to creating your first ECS application.
Installation
Section titled “Installation”Using CLI (Recommended)
Section titled “Using CLI (Recommended)”The easiest way to add ECS to your existing project:
# In your project directorynpx @esengine/cli initThe CLI automatically detects your project type (Cocos Creator 2.x/3.x, LayaAir 3.x, or Node.js) and generates the necessary integration code, including:
ECSManagercomponent/script - Manages ECS lifecycle- Example components and systems - Helps you get started quickly
- Automatic dependency installation
Manual NPM Installation
Section titled “Manual NPM Installation”If you prefer manual configuration:
# Using npmnpm install @esengine/ecs-frameworkInitialize Core
Section titled “Initialize Core”Basic Initialization
Section titled “Basic Initialization”The core of ECS Framework is the Core class, a singleton that manages the entire framework lifecycle.
import { Core } from '@esengine/ecs-framework'
// Method 1: Using config object (recommended)const core = Core.create({ debug: true, // Enable debug mode for detailed logs and performance monitoring debugConfig: { // Optional: Advanced debug configuration enabled: false, // Whether to enable WebSocket debug server websocketUrl: 'ws://localhost:8080', debugFrameRate: 30, // Debug data send frame rate channels: { entities: true, systems: true, performance: true, components: true, scenes: true } }});
// Method 2: Simplified creation (backward compatible)const core = Core.create(true); // Equivalent to { debug: true }
// Method 3: Production environment configurationconst core = Core.create({ debug: false // Disable debug in production});Core Configuration Details
Section titled “Core Configuration Details”interface ICoreConfig { /** Enable debug mode - affects log level and performance monitoring */ debug?: boolean;
/** Advanced debug configuration - for dev tools integration */ debugConfig?: { enabled: boolean; // Enable debug server websocketUrl: string; // WebSocket server URL autoReconnect?: boolean; // Auto reconnect debugFrameRate?: 60 | 30 | 15; // Debug data send frame rate channels: { // Data channel configuration entities: boolean; // Entity data systems: boolean; // System data performance: boolean; // Performance data components: boolean; // Component data scenes: boolean; // Scene data }; };}Core Instance Management
Section titled “Core Instance Management”Core uses singleton pattern, accessible via static property after creation:
// Create instanceconst core = Core.create(true);
// Get created instanceconst instance = Core.Instance; // Returns current instance, null if not createdGame Loop Integration
Section titled “Game Loop Integration”Important: Before creating entities and systems, you need to understand how to integrate ECS Framework into your game engine.
Core.update(deltaTime) is the framework heartbeat, must be called every frame. It handles:
- Updating the built-in Time class
- Updating all global managers (timers, object pools, etc.)
- Updating all entity systems in all scenes
- Processing entity creation and destruction
- Collecting performance data (in debug mode)
See engine integration examples: Game Engine Integration
Create Your First ECS Application
Section titled “Create Your First ECS Application”1. Define Components
Section titled “1. Define Components”Components are pure data containers that store entity state:
import { Component, ECSComponent } from '@esengine/ecs-framework'
// Position component@ECSComponent('Position')class Position extends Component { x: number = 0 y: number = 0
constructor(x: number = 0, y: number = 0) { super() this.x = x this.y = y }}
// Velocity component@ECSComponent('Velocity')class Velocity extends Component { dx: number = 0 dy: number = 0
constructor(dx: number = 0, dy: number = 0) { super() this.dx = dx this.dy = dy }}
// Sprite component@ECSComponent('Sprite')class Sprite extends Component { texture: string = '' width: number = 32 height: number = 32
constructor(texture: string, width: number = 32, height: number = 32) { super() this.texture = texture this.width = width this.height = height }}2. Create Entity Systems
Section titled “2. Create Entity Systems”Systems contain game logic and process entities with specific components. ECS Framework provides Matcher-based entity filtering:
import { EntitySystem, Matcher, Time, ECSSystem } from '@esengine/ecs-framework'
// Movement system - handles position and velocity@ECSSystem('MovementSystem')class MovementSystem extends EntitySystem {
constructor() { // Use Matcher to define target entities: must have both Position and Velocity super(Matcher.empty().all(Position, Velocity)) }
protected process(entities: readonly Entity[]): void { // process method receives all matching entities for (const entity of entities) { const position = entity.getComponent(Position)! const velocity = entity.getComponent(Velocity)!
// Update position (using framework's Time class) position.x += velocity.dx * Time.deltaTime position.y += velocity.dy * Time.deltaTime
// Boundary check example if (position.x < 0) position.x = 0 if (position.y < 0) position.y = 0 } }}
// Render system - handles visible objects@ECSSystem('RenderSystem')class RenderSystem extends EntitySystem {
constructor() { // Must have Position and Sprite, optional Velocity (for direction) super(Matcher.empty().all(Position, Sprite).any(Velocity)) }
protected process(entities: readonly Entity[]): void { for (const entity of entities) { const position = entity.getComponent(Position)! const sprite = entity.getComponent(Sprite)! const velocity = entity.getComponent(Velocity) // May be null
// Flip sprite based on velocity direction (optional logic) let flipX = false if (velocity && velocity.dx < 0) { flipX = true }
// Render logic (pseudocode here) this.drawSprite(sprite.texture, position.x, position.y, sprite.width, sprite.height, flipX) } }
private drawSprite(texture: string, x: number, y: number, width: number, height: number, flipX: boolean = false) { // Actual render implementation depends on your game engine const direction = flipX ? '<-' : '->' console.log(`Render ${texture} at (${x.toFixed(1)}, ${y.toFixed(1)}) direction: ${direction}`) }}3. Create Scene
Section titled “3. Create Scene”Recommended to extend Scene class for custom scenes:
import { Scene } from '@esengine/ecs-framework'
// Recommended: Extend Scene for custom sceneclass GameScene extends Scene {
initialize(): void { // Scene initialization logic this.name = "MainScene";
// Add systems to scene this.addSystem(new MovementSystem()); this.addSystem(new RenderSystem()); }
onStart(): void { // Logic when scene starts running console.log("Game scene started"); }
unload(): void { // Cleanup logic when scene unloads console.log("Game scene unloaded"); }}
// Create and set sceneconst gameScene = new GameScene();Core.setScene(gameScene);4. Create Entities
Section titled “4. Create Entities”// Create player entityconst player = gameScene.createEntity("Player");player.addComponent(new Position(100, 100));player.addComponent(new Velocity(50, 30)); // Move 50px/sec (x), 30px/sec (y)player.addComponent(new Sprite("player.png", 64, 64));Scene Management
Section titled “Scene Management”Core has built-in scene management, very simple to use:
import { Core, Scene } from '@esengine/ecs-framework';
// Initialize CoreCore.create({ debug: true });
// Create and set sceneclass GameScene extends Scene { initialize(): void { this.name = "GamePlay"; this.addSystem(new MovementSystem()); this.addSystem(new RenderSystem()); }}
const gameScene = new GameScene();Core.setScene(gameScene);
// Game loop (auto-updates scene)function gameLoop(deltaTime: number) { Core.update(deltaTime); // Auto-updates global services and scene}
// Switch scenesCore.loadScene(new MenuScene()); // Delayed switch (next frame)Core.setScene(new GameScene()); // Immediate switch
// Access current sceneconst currentScene = Core.scene;
// Using fluent APIconst player = Core.ecsAPI?.createEntity('Player') .addComponent(Position, 100, 100) .addComponent(Velocity, 50, 0);Advanced: Using WorldManager for Multi-World
Section titled “Advanced: Using WorldManager for Multi-World”Only for complex server-side applications (MMO game servers, game room systems, etc.):
import { Core, WorldManager } from '@esengine/ecs-framework';
// Initialize CoreCore.create({ debug: true });
// Get WorldManager from service container (Core auto-creates and registers it)const worldManager = Core.services.resolve(WorldManager);
// Create multiple independent game worldsconst room1 = worldManager.createWorld('room_001');const room2 = worldManager.createWorld('room_002');
// Create scenes in each worldconst gameScene1 = room1.createScene('game', new GameScene());const gameScene2 = room2.createScene('game', new GameScene());
// Activate scenesroom1.setSceneActive('game', true);room2.setSceneActive('game', true);
// Game loop (need to manually update worlds)function gameLoop(deltaTime: number) { Core.update(deltaTime); // Update global services worldManager.updateAll(); // Manually update all worlds}Game Engine Integration
Section titled “Game Engine Integration”Laya 3.x Engine Integration
Section titled “Laya 3.x Engine Integration”Using Laya.Script component to manage ECS lifecycle is recommended:
import { Core, Scene } from '@esengine/ecs-framework';
const { regClass } = Laya;
@regClass()export class ECSManager extends Laya.Script { private ecsScene = new GameScene();
onAwake(): void { // Initialize ECS Core.create({ debug: true }); Core.setScene(this.ecsScene); }
onUpdate(): void { // Auto-updates global services and scene Core.update(Laya.timer.delta / 1000); }
onDestroy(): void { // Cleanup resources Core.destroy(); }}In Laya IDE, attach the ECSManager script to a node in your scene.
Cocos Creator Integration
Section titled “Cocos Creator Integration”import { Component, _decorator } from 'cc';import { Core } from '@esengine/ecs-framework';
const { ccclass } = _decorator;
@ccclass('ECSGameManager')export class ECSGameManager extends Component { onLoad() { // Initialize ECS Core.create(true); Core.setScene(new GameScene()); }
update(deltaTime: number) { // Auto-updates global services and scene Core.update(deltaTime); }
onDestroy() { // Cleanup resources Core.destroy(); }}Next Steps
Section titled “Next Steps”You’ve successfully created your first ECS application! Next you can:
- Check the complete API Documentation
- Explore more practical examples
Why isn’t my system executing?
Section titled “Why isn’t my system executing?”Ensure:
- System is added to scene:
this.addSystem(system)(in Scene’s initialize method) - Scene is set:
Core.setScene(scene) - Game loop is calling:
Core.update(deltaTime)
How to debug ECS applications?
Section titled “How to debug ECS applications?”Enable debug mode:
Core.create({ debug: true })
// Get debug dataconst debugData = Core.getDebugData()console.log(debugData)