System Architecture
In ECS architecture, Systems are where business logic is processed. Systems are responsible for performing operations on entities that have specific component combinations, serving as the logic processing units of ECS architecture.
Basic Concepts
Section titled “Basic Concepts”Systems are concrete classes that inherit from the EntitySystem abstract base class, used for:
- Defining entity processing logic (such as movement, collision detection, rendering, etc.)
- Filtering entities based on component combinations
- Providing lifecycle management and performance monitoring
- Managing entity add/remove events
Quick Example
Section titled “Quick Example”import { EntitySystem, ECSSystem, Matcher } from '@esengine/ecs-framework';
@ECSSystem('Movement')class MovementSystem extends EntitySystem { constructor() { // Use Matcher to define entity conditions to process super(Matcher.all(Position, Velocity)); }
protected process(entities: readonly Entity[]): void { for (const entity of entities) { const position = entity.getComponent(Position); const velocity = entity.getComponent(Velocity);
if (position && velocity) { position.x += velocity.dx * Time.deltaTime; position.y += velocity.dy * Time.deltaTime; } } }}System Properties and Methods
Section titled “System Properties and Methods”Important Properties
Section titled “Important Properties”@ECSSystem('Example')class ExampleSystem extends EntitySystem { showSystemInfo(): void { console.log(`System name: ${this.systemName}`); // System name console.log(`Update order: ${this.updateOrder}`); // Update order console.log(`Is enabled: ${this.enabled}`); // Enabled state console.log(`Entity count: ${this.entities.length}`); // Number of matched entities console.log(`Scene: ${this.scene?.name}`); // Parent scene }}Entity Access
Section titled “Entity Access”protected process(entities: readonly Entity[]): void { // Method 1: Use entity list from parameter for (const entity of entities) { // Process entity }
// Method 2: Use this.entities property (same as parameter) for (const entity of this.entities) { // Process entity }}Controlling System Execution
Section titled “Controlling System Execution”@ECSSystem('Conditional')class ConditionalSystem extends EntitySystem { private shouldProcess = true;
protected onCheckProcessing(): boolean { // Return false to skip this processing return this.shouldProcess && this.entities.length > 0; }
public pause(): void { this.shouldProcess = false; }
public resume(): void { this.shouldProcess = true; }}System Management
Section titled “System Management”Adding Systems to Scene
Section titled “Adding Systems to Scene”The framework provides two ways to add systems: pass an instance or pass a type (automatic dependency injection).
// Add systems in scene subclassclass GameScene extends Scene { protected initialize(): void { // Method 1: Pass instance this.addSystem(new MovementSystem()); this.addSystem(new RenderSystem());
// Method 2: Pass type (automatic dependency injection) this.addEntityProcessor(PhysicsSystem);
// Set system update order const movementSystem = this.getSystem(MovementSystem); if (movementSystem) { movementSystem.updateOrder = 1; } }}System Update Order
Section titled “System Update Order”System execution order is determined by the updateOrder property. Lower values execute first:
@ECSSystem('Input')class InputSystem extends EntitySystem { constructor() { super(Matcher.all(InputComponent)); this.updateOrder = -100; // Input system executes first }}
@ECSSystem('Physics')class PhysicsSystem extends EntitySystem { constructor() { super(Matcher.all(RigidBody)); this.updateOrder = 0; // Default order }}
@ECSSystem('Render')class RenderSystem extends EntitySystem { constructor() { super(Matcher.all(Sprite, Transform)); this.updateOrder = 100; // Render system executes last }}Stable Sorting: addOrder
Section titled “Stable Sorting: addOrder”When multiple systems have the same updateOrder, the framework uses addOrder (add order) as a secondary sorting criterion:
// Both systems have default updateOrder of 0scene.addSystem(new SystemA()); // addOrder = 0, executes firstscene.addSystem(new SystemB()); // addOrder = 1, executes secondRuntime Environment Decorators
Section titled “Runtime Environment Decorators”For networked games, you can use decorators to control which environment a system method runs in.
Available Decorators
Section titled “Available Decorators”| Decorator | Effect |
|---|---|
@ServerOnly() | Method only executes on server |
@ClientOnly() | Method only executes on client |
@NotServer() | Method skipped on server |
@NotClient() | Method skipped on client |
Usage Example
Section titled “Usage Example”import { EntitySystem, ServerOnly, ClientOnly } from '@esengine/ecs-framework';
class GameSystem extends EntitySystem { @ServerOnly() private spawnEnemies(): void { // Only runs on server - authoritative spawn logic }
@ClientOnly() private playEffects(): void { // Only runs on client - visual effects }}Simple Conditional Check
Section titled “Simple Conditional Check”For simple cases, a direct check is often clearer than decorators:
class CollectibleSystem extends EntitySystem { private checkCollections(): void { if (!this.scene.isServer) return; // Skip on client
// Server-authoritative logic... }}See Scene Runtime Environment for configuration details.
Next Steps
Section titled “Next Steps”- System Types - Learn about different system base classes
- System Lifecycle - Lifecycle callbacks and event listening
- Command Buffer - Deferred entity operations
- System Scheduling - Declarative system scheduling
- Change Detection - Frame-level change detection optimization
- Best Practices - System design best practices