# 系统架构 在 ECS 架构中,系统(System)是处理业务逻辑的地方。系统负责对拥有特定组件组合的实体执行操作,是 ECS 架构的逻辑处理单元。 ## 基本概念 系统是继承自 `EntitySystem` 抽象基类的具体类,用于: - 定义实体的处理逻辑(如移动、碰撞检测、渲染等) - 根据组件组合筛选需要处理的实体 - 提供生命周期管理和性能监控 - 管理实体的添加、移除事件 ## 系统类型 框架提供了几种不同类型的系统基类: ### EntitySystem - 基础系统 最基础的系统类,所有其他系统都继承自它: ```typescript import { EntitySystem, ECSSystem, Matcher } from '@esengine/ecs-framework'; @ECSSystem('Movement') class MovementSystem extends EntitySystem { constructor() { // 使用 Matcher 定义需要处理的实体条件 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; } } } } ``` ### ProcessingSystem - 处理系统 适用于不需要逐个处理实体的系统: ```typescript @ECSSystem('Physics') class PhysicsSystem extends ProcessingSystem { constructor() { super(); // 不需要指定 Matcher } public processSystem(): void { // 执行物理世界步进 this.physicsWorld.step(Time.deltaTime); } } ``` ### PassiveSystem - 被动系统 被动系统不进行主动处理,主要用于监听实体的添加和移除事件: ```typescript @ECSSystem('EntityTracker') class EntityTrackerSystem extends PassiveSystem { constructor() { super(Matcher.all(Health)); } protected onAdded(entity: Entity): void { console.log(`生命值实体被添加: ${entity.name}`); } protected onRemoved(entity: Entity): void { console.log(`生命值实体被移除: ${entity.name}`); } } ``` ### IntervalSystem - 间隔系统 按固定时间间隔执行的系统: ```typescript @ECSSystem('AutoSave') class AutoSaveSystem extends IntervalSystem { constructor() { // 每 5 秒执行一次 super(5.0, Matcher.all(SaveData)); } protected process(entities: readonly Entity[]): void { console.log('执行自动保存...'); // 保存游戏数据 this.saveGameData(entities); } private saveGameData(entities: readonly Entity[]): void { // 保存逻辑 } } ``` ### WorkerEntitySystem - 多线程系统 基于Web Worker的多线程处理系统,适用于计算密集型任务,能够充分利用多核CPU性能。 Worker系统提供了真正的并行计算能力,支持SharedArrayBuffer优化,并具有自动降级支持。特别适合物理模拟、粒子系统、AI计算等场景。 **详细内容请参考:[Worker系统](/guide/worker-system)** ## 实体匹配器 (Matcher) Matcher 用于定义系统需要处理哪些实体。它提供了灵活的条件组合: ### 基本匹配条件 ```typescript // 必须同时拥有 Position 和 Velocity 组件 const matcher1 = Matcher.all(Position, Velocity); // 至少拥有 Health 或 Shield 组件之一 const matcher2 = Matcher.any(Health, Shield); // 不能拥有 Dead 组件 const matcher3 = Matcher.none(Dead); ``` ### 复合匹配条件 ```typescript // 复杂的组合条件 const complexMatcher = Matcher.all(Position, Velocity) .any(Player, Enemy) .none(Dead, Disabled); @ECSSystem('Combat') class CombatSystem extends EntitySystem { constructor() { super(complexMatcher); } } ``` ### 特殊匹配条件 ```typescript // 按标签匹配 const tagMatcher = Matcher.byTag(1); // 匹配标签为 1 的实体 // 按名称匹配 const nameMatcher = Matcher.byName("Player"); // 匹配名称为 "Player" 的实体 // 单组件匹配 const componentMatcher = Matcher.byComponent(Health); // 匹配拥有 Health 组件的实体 ``` ## 系统生命周期 系统提供了完整的生命周期回调: ```typescript @ECSSystem('Example') class ExampleSystem extends EntitySystem { protected onInitialize(): void { console.log('系统初始化'); // 系统被添加到场景时调用,用于初始化资源 } protected onBegin(): void { // 每帧处理开始前调用 } protected process(entities: readonly Entity[]): void { // 主要的处理逻辑 for (const entity of entities) { // 处理每个实体 } } protected lateProcess(entities: readonly Entity[]): void { // 主处理之后的后期处理 } protected onEnd(): void { // 每帧处理结束后调用 } protected onDestroy(): void { console.log('系统销毁'); // 系统从场景移除时调用,用于清理资源 } } ``` ## 实体事件监听 系统可以监听实体的添加和移除事件: ```typescript @ECSSystem('EnemyManager') class EnemyManagerSystem extends EntitySystem { private enemyCount = 0; constructor() { super(Matcher.all(Enemy, Health)); } protected onAdded(entity: Entity): void { this.enemyCount++; console.log(`敌人加入战斗,当前敌人数量: ${this.enemyCount}`); // 可以在这里为新敌人设置初始状态 const health = entity.getComponent(Health); if (health) { health.current = health.max; } } protected onRemoved(entity: Entity): void { this.enemyCount--; console.log(`敌人被移除,剩余敌人数量: ${this.enemyCount}`); // 检查是否所有敌人都被消灭 if (this.enemyCount === 0) { this.scene?.eventSystem.emitSync('all_enemies_defeated'); } } } ``` ## 系统属性和方法 ### 重要属性 ```typescript @ECSSystem('Example') class ExampleSystem extends EntitySystem { showSystemInfo(): void { console.log(`系统名称: ${this.systemName}`); // 系统名称 console.log(`更新顺序: ${this.updateOrder}`); // 更新时序 console.log(`是否启用: ${this.enabled}`); // 启用状态 console.log(`实体数量: ${this.entities.length}`); // 匹配的实体数量 console.log(`所属场景: ${this.scene?.name}`); // 所属场景 } } ``` ### 实体访问 ```typescript protected process(entities: readonly Entity[]): void { // 方式1:使用参数中的实体列表 for (const entity of entities) { // 处理实体 } // 方式2:使用 this.entities 属性(与参数相同) for (const entity of this.entities) { // 处理实体 } } ``` ### 控制系统执行 ```typescript @ECSSystem('Conditional') class ConditionalSystem extends EntitySystem { private shouldProcess = true; protected onCheckProcessing(): boolean { // 返回 false 时跳过本次处理 return this.shouldProcess && this.entities.length > 0; } public pause(): void { this.shouldProcess = false; } public resume(): void { this.shouldProcess = true; } } ``` ## 事件系统集成 系统可以方便地监听和发送事件: ```typescript @ECSSystem('GameLogic') class GameLogicSystem extends EntitySystem { protected onInitialize(): void { // 添加事件监听器(系统销毁时自动清理) this.addEventListener('player_died', this.onPlayerDied.bind(this)); this.addEventListener('level_complete', this.onLevelComplete.bind(this)); } private onPlayerDied(data: any): void { console.log('玩家死亡,重新开始游戏'); // 处理玩家死亡逻辑 } private onLevelComplete(data: any): void { console.log('关卡完成,加载下一关'); // 处理关卡完成逻辑 } protected process(entities: readonly Entity[]): void { // 在处理过程中发送事件 for (const entity of entities) { const health = entity.getComponent(Health); if (health && health.current <= 0) { this.scene?.eventSystem.emitSync('entity_died', { entity }); } } } } ``` ## 性能监控 系统内置了性能监控功能: ```typescript @ECSSystem('Performance') class PerformanceSystem extends EntitySystem { protected onEnd(): void { // 获取性能数据 const perfData = this.getPerformanceData(); if (perfData) { console.log(`执行时间: ${perfData.executionTime.toFixed(2)}ms`); } // 获取性能统计 const stats = this.getPerformanceStats(); if (stats) { console.log(`平均执行时间: ${stats.averageTime.toFixed(2)}ms`); } } public resetPerformance(): void { this.resetPerformanceData(); } } ``` ## 系统管理 ### 添加系统到场景 ```typescript // 在场景子类中添加系统 class GameScene extends Scene { protected initialize(): void { // 添加系统 this.addSystem(new MovementSystem()); this.addSystem(new RenderSystem()); this.addSystem(new PhysicsSystem()); // 设置系统更新顺序 const movementSystem = this.getSystem(MovementSystem); if (movementSystem) { movementSystem.updateOrder = 1; } } } ``` ### 系统更新顺序 ```typescript @ECSSystem('Input') class InputSystem extends EntitySystem { constructor() { super(Matcher.all(InputComponent)); this.updateOrder = -100; // 输入系统优先执行 } } @ECSSystem('Physics') class PhysicsSystem extends EntitySystem { constructor() { super(Matcher.all(RigidBody)); this.updateOrder = 0; // 默认顺序 } } @ECSSystem('Render') class RenderSystem extends EntitySystem { constructor() { super(Matcher.all(Sprite, Transform)); this.updateOrder = 100; // 渲染系统最后执行 } } ``` ## 复杂系统示例 ### 碰撞检测系统 ```typescript @ECSSystem('Collision') class CollisionSystem extends EntitySystem { constructor() { super(Matcher.all(Transform, Collider)); } protected process(entities: readonly Entity[]): void { // 简单的 n² 碰撞检测 for (let i = 0; i < entities.length; i++) { for (let j = i + 1; j < entities.length; j++) { this.checkCollision(entities[i], entities[j]); } } } private checkCollision(entityA: Entity, entityB: Entity): void { const transformA = entityA.getComponent(Transform); const transformB = entityB.getComponent(Transform); const colliderA = entityA.getComponent(Collider); const colliderB = entityB.getComponent(Collider); if (this.isColliding(transformA, colliderA, transformB, colliderB)) { // 发送碰撞事件 this.scene?.eventSystem.emitSync('collision', { entityA, entityB }); } } private isColliding(transformA: Transform, colliderA: Collider, transformB: Transform, colliderB: Collider): boolean { // 碰撞检测逻辑 return false; // 简化示例 } } ``` ### 状态机系统 ```typescript @ECSSystem('StateMachine') class StateMachineSystem extends EntitySystem { constructor() { super(Matcher.all(StateMachine)); } protected process(entities: readonly Entity[]): void { for (const entity of entities) { const stateMachine = entity.getComponent(StateMachine); if (stateMachine) { stateMachine.updateTimer(Time.deltaTime); this.updateState(entity, stateMachine); } } } private updateState(entity: Entity, stateMachine: StateMachine): void { switch (stateMachine.currentState) { case EntityState.Idle: this.handleIdleState(entity, stateMachine); break; case EntityState.Moving: this.handleMovingState(entity, stateMachine); break; case EntityState.Attacking: this.handleAttackingState(entity, stateMachine); break; } } private handleIdleState(entity: Entity, stateMachine: StateMachine): void { // 空闲状态逻辑 } private handleMovingState(entity: Entity, stateMachine: StateMachine): void { // 移动状态逻辑 } private handleAttackingState(entity: Entity, stateMachine: StateMachine): void { // 攻击状态逻辑 } } ``` ## 最佳实践 ### 1. 系统单一职责 ```typescript // ✅ 好的系统设计 - 职责单一 @ECSSystem('Movement') class MovementSystem extends EntitySystem { constructor() { super(Matcher.all(Position, Velocity)); } } @ECSSystem('Rendering') class RenderingSystem extends EntitySystem { constructor() { super(Matcher.all(Sprite, Transform)); } } // ❌ 避免的系统设计 - 职责过多 @ECSSystem('GameSystem') class GameSystem extends EntitySystem { // 一个系统处理移动、渲染、音效等多种逻辑 } ``` ### 2. 使用装饰器 **必须使用 `@ECSSystem` 装饰器**: ```typescript // ✅ 正确的用法 @ECSSystem('Physics') class PhysicsSystem extends EntitySystem { // 系统实现 } // ❌ 错误的用法 - 没有装饰器 class BadSystem extends EntitySystem { // 这样定义的系统可能在生产环境出现问题 } ``` ### 3. 合理的更新顺序 ```typescript // 按逻辑顺序设置系统的更新时序 @ECSSystem('Input') class InputSystem extends EntitySystem { constructor() { super(); this.updateOrder = -100; // 最先处理输入 } } @ECSSystem('Logic') class GameLogicSystem extends EntitySystem { constructor() { super(); this.updateOrder = 0; // 处理游戏逻辑 } } @ECSSystem('Render') class RenderSystem extends EntitySystem { constructor() { super(); this.updateOrder = 100; // 最后进行渲染 } } ``` ### 4. 避免在系统间直接引用 ```typescript // ❌ 避免:系统间直接引用 @ECSSystem('Bad') class BadSystem extends EntitySystem { private otherSystem: SomeOtherSystem; // 避免直接引用其他系统 } // ✅ 推荐:通过事件系统通信 @ECSSystem('Good') class GoodSystem extends EntitySystem { protected process(entities: readonly Entity[]): void { // 通过事件系统与其他系统通信 this.scene?.eventSystem.emitSync('data_updated', { entities }); } } ``` ### 5. 及时清理资源 ```typescript @ECSSystem('Resource') class ResourceSystem extends EntitySystem { private resources: Map = new Map(); protected onDestroy(): void { // 清理资源 for (const [key, resource] of this.resources) { if (resource.dispose) { resource.dispose(); } } this.resources.clear(); } } ``` 系统是 ECS 架构的逻辑处理核心,正确设计和使用系统能让你的游戏代码更加模块化、高效和易于维护。