# ECS架构深度解析 **本文档引用的文件** - [BattleMoveComp.ts](file://assets/script/game/common/ecs/position/BattleMoveComp.ts) - [BattleMoveSystem.ts](file://assets/script/game/common/ecs/position/BattleMoveSystem.ts) - [EcsPositionSystem.ts](file://assets/script/game/common/ecs/position/EcsPositionSystem.ts) - [HeroViewComp.ts](file://assets/script/game/hero/HeroViewComp.ts) - [MapModelComp.ts](file://assets/script/game/map/model/MapModelComp.ts) - [SingletonModuleComp.ts](file://assets/script/game/common/SingletonModuleComp.ts) - [ecs.md](file://doc/ecs/ecs.md) - [Main.ts](file://assets/script/Main.ts) - [HeroAtk.ts](file://assets/script/game/hero/HeroAtk.ts) - *在最近的提交中更新* - [HeroAttrsComp.ts](file://assets/script/game/hero/HeroAttrsComp.ts) - *在最近的提交中更新* - [HSkillSystem.ts](file://assets/script/game/hero/HSkillSystem.ts) - *在最近的提交中添加* ## 更新摘要 **已做更改** - 更新了组件注册机制部分,以反映在多个系统中添加ECS注册装饰器的更改 - 添加了关于技能系统的新部分,包括CastSkillRequestComp、SkillCastSystem、SkillCDSystem和SkillAutocastSystem - 更新了实际案例分析,以包含新的技能系统实现 - 在扩展开发指南中添加了新的系统接口示例 - 更新了文档来源以包含新分析的文件 ## 目录 1. [简介](#简介) 2. [ECS架构概述](#ecs架构概述) 3. [组件系统详解](#组件系统详解) 4. [实体生命周期管理](#实体生命周期管理) 5. [系统架构与执行机制](#系统架构与执行机制) 6. [实际案例分析](#实际案例分析) 7. [性能优化与最佳实践](#性能优化与最佳实践) 8. [扩展开发指南](#扩展开发指南) 9. [总结](#总结) ## 简介 ECS(Entity-Component-System)是一种流行的游戏架构模式,它通过将数据与行为分离来实现高度模块化和可扩展的系统设计。本项目采用TypeScript版本的ECS框架,实现了游戏逻辑的数据与行为解耦,为复杂的游戏系统提供了清晰的架构基础。 ## ECS架构概述 ### 核心概念 ECS架构由三个核心元素组成: ```mermaid graph TB subgraph "ECS架构核心" Entity["实体 (Entity)
唯一标识符"] Component["组件 (Component)
数据容器"] System["系统 (System)
逻辑处理器"] end subgraph "交互关系" Entity --> Component System --> Entity System -.-> Component end subgraph "执行流程" System --> Filter["筛选机制"] Filter --> Entities["符合条件的实体"] Entities --> Update["系统更新"] end ``` **图表来源** - [ecs.md](file://doc/ecs/ecs.md#L1-L27) ### 架构优势 1. **数据与行为分离**:组件只存储数据,系统处理逻辑 2. **高度模块化**:通过组合不同组件创建复杂实体 3. **性能优化**:批量处理相同类型的操作 4. **易于扩展**:新增功能只需添加新组件和系统 ## 组件系统详解 ### 组件注册机制 组件通过装饰器`@ecs.register`进行注册,框架自动管理组件的生命周期和内存回收。最近的代码重构为多个英雄系统添加了ECS注册装饰器,使架构更符合标准。 ```mermaid classDiagram class Component { <> +reset() void } class BattleMoveComp { +number direction +number targetX +boolean moving +reset() void } class HeroViewComp { +string hero_name +number fac +boolean is_dead +number[] Attrs +reset() void } class MapModelComp { +number id +string resPrefab +reset() void } Component <|-- BattleMoveComp Component <|-- HeroViewComp Component <|-- MapModelComp ``` **图表来源** - [BattleMoveComp.ts](file://assets/script/game/common/ecs/position/BattleMoveComp.ts#L1-L16) - [HeroViewComp.ts](file://assets/script/game/hero/HeroViewComp.ts#L1-L50) - [MapModelComp.ts](file://assets/script/game/map/model/MapModelComp.ts#L1-L43) ### 组件添加与移除机制 组件的添加和移除遵循严格的生命周期管理: ```mermaid sequenceDiagram participant Entity as 实体 participant ECS as ECS框架 participant Pool as 组件池 participant System as 系统 Entity->>ECS : add(Component) ECS->>Pool : 获取可用组件 alt 组件池中有可用组件 Pool-->>ECS : 返回组件实例 else 组件池为空 ECS->>ECS : 创建新组件 end ECS->>Entity : 绑定组件 System->>Entity : 筛选实体 Entity-->>System : 返回实体列表 Entity->>ECS : remove(Component) ECS->>Component : reset()重置状态 ECS->>Pool : 回收组件到池中 ``` **图表来源** - [ecs.md](file://doc/ecs/ecs.md#L45-L87) **章节来源** - [BattleMoveComp.ts](file://assets/script/game/common/ecs/position/BattleMoveComp.ts#L1-L16) - [ecs.md](file://doc/ecs/ecs.md#L15-L45) ## 实体生命周期管理 ### 实体创建与销毁 实体通过继承`ecs.Entity`创建,并支持父子实体关系管理: ```mermaid stateDiagram-v2 [*] --> Created : createEntity() Created --> Active : addComponents() Active --> Updated : systemUpdate() Updated --> Active : continue Active --> Removed : removeComponents() Removed --> Destroyed : destroy() Destroyed --> [*] Active --> Paused : systemPause() Paused --> Active : systemResume() ``` ### 实体管理操作 | 操作 | 方法 | 描述 | |------|------|------| | 创建实体 | `ecs.getEntity()` | 从实体池中获取或创建新实体 | | 添加组件 | `entity.add(Component)` | 优先从组件池获取,否则创建新实例 | | 移除组件 | `entity.remove(Component)` | 组件重置后放回组件池 | | 销毁实体 | `entity.destroy()` | 清理所有组件并回收实体 | | 子实体管理 | `addChild(Entity)` | 管理实体间的父子关系 | **章节来源** - [ecs.md](file://doc/ecs/ecs.md#L29-L87) ## 系统架构与执行机制 ### 系统层次结构 ```mermaid classDiagram class System { <> +execute(dt) void } class ComblockSystem { +filter() IMatcher +update(entity) void +entityEnter(entity) void +entityRemove(entity) void } class BattleMoveSystem { +filter() IMatcher +update(entity) void -checkEnemiesExist(entity) boolean -findNearestEnemy(entity) HeroViewComp -validatePosition(x, move) boolean } class EcsPositionSystem { +constructor() } System <|-- ComblockSystem ComblockSystem <|-- BattleMoveSystem System <|-- EcsPositionSystem ``` **图表来源** - [BattleMoveSystem.ts](file://assets/script/game/common/ecs/position/BattleMoveSystem.ts#L1-L50) - [EcsPositionSystem.ts](file://assets/script/game/common/ecs/position/EcsPositionSystem.ts#L1-L9) ### 筛选机制 系统通过`filter()`方法筛选符合条件的实体: ```mermaid flowchart TD Start([系统执行]) --> Filter["filter()筛选"] Filter --> Matcher{"IMatcher匹配"} Matcher --> |allOf| AllMatch["所有组件都存在"] Matcher --> |anyOf| AnyMatch["至少有一个组件存在"] Matcher --> |excludeOf| ExcludeMatch["不包含指定组件"] Matcher --> |onlyOf| OnlyMatch["只有指定组件"] AllMatch --> ProcessEntities["处理实体列表"] AnyMatch --> ProcessEntities ExcludeMatch --> ProcessEntities OnlyMatch --> ProcessEntities ProcessEntities --> Update["系统更新"] Update --> End([完成]) ``` **图表来源** - [ecs.md](file://doc/ecs/ecs.md#L88-L128) ### 系统执行流程 ```mermaid sequenceDiagram participant Root as RootSystem participant System as ComblockSystem participant Entity as Entity participant Component as Component Root->>System : execute(dt) System->>System : filter()筛选实体 loop 遍历符合条件的实体 System->>Entity : entityEnter()首次进入 System->>Entity : update()每帧更新 Entity->>Component : get(Component) Component-->>Entity : 返回组件实例 System->>Entity : 处理业务逻辑 end System->>Entity : entityRemove()移除处理 ``` **图表来源** - [BattleMoveSystem.ts](file://assets/script/game/common/ecs/position/BattleMoveSystem.ts#L10-L30) **章节来源** - [BattleMoveSystem.ts](file://assets/script/game/common/ecs/position/BattleMoveSystem.ts#L1-L272) - [EcsPositionSystem.ts](file://assets/script/game/common/ecs/position/EcsPositionSystem.ts#L1-L9) ## 实际案例分析 ### BattleMoveSystem详细分析 BattleMoveSystem展示了ECS架构在游戏AI中的应用: #### 组件依赖关系 ```mermaid graph LR Entity["游戏实体"] --> BattleMoveComp["BattleMoveComp
移动控制"] Entity --> HeroViewComp["HeroViewComp
视图控制"] BattleMoveComp --> Direction["direction
移动方向"] BattleMoveComp --> TargetX["targetX
目标位置"] BattleMoveComp --> Moving["moving
移动状态"] HeroViewComp --> HP["hp/mp
生命值"] HeroViewComp --> Status["status
状态"] HeroViewComp --> Position["node.position
位置信息"] ``` **图表来源** - [BattleMoveSystem.ts](file://assets/script/game/common/ecs/position/BattleMoveSystem.ts#L10-L20) - [BattleMoveComp.ts](file://assets/script/game/common/ecs/position/BattleMoveComp.ts#L4-L12) #### 系统更新逻辑 BattleMoveSystem的核心更新逻辑体现了ECS的优势: 1. **数据分离**:移动逻辑完全封装在系统中 2. **条件筛选**:只处理同时拥有BattleMoveComp和HeroViewComp的实体 3. **状态管理**:根据游戏状态动态调整行为 4. **性能优化**:只处理活跃实体,避免不必要的计算 #### 关键算法实现 | 算法 | 功能 | 实现位置 | |------|------|----------| | 敌人检测 | 检查攻击范围内是否有敌人 | `checkEnemiesInRange()` | | 最近敌人查找 | 寻找最近的敌对单位 | `findNearestEnemy()` | | 位置验证 | 验证移动位置的有效性 | `validatePosition()` | | 渲染层级更新 | 根据位置更新渲染顺序 | `updateRenderOrder()` | **章节来源** - [BattleMoveSystem.ts](file://assets/script/game/common/ecs/position/BattleMoveSystem.ts#L15-L272) ### HeroViewComp综合组件分析 HeroViewComp展示了组件如何存储复杂的游戏状态: #### 属性管理系统 ```mermaid classDiagram class HeroViewComp { +Record~number,Array~ BUFFS +Record~number,Array~ BUFFS_TEMP +number[] Attrs +number[] NeAttrs +addBuff(conf) void +recalculateSingleAttr(attrIndex) void +updateTemporaryBuffsDebuffs(dt) void } class BuffInstance { +number value +BType BType +number remainTime } HeroViewComp --> BuffInstance : 管理 ``` **图表来源** - [HeroViewComp.ts](file://assets/script/game/hero/HeroViewComp.ts#L60-L120) #### BUFF系统架构 HeroViewComp实现了复杂的BUFF/DEBUFF管理系统: 1. **持久BUFF**:存储在`BUFFS`数组中,永久存在直到手动移除 2. **临时BUFF**:存储在`BUFFS_TEMP`数组中,带有剩余时间 3. **属性计算**:根据数值型和百分比型BUFF计算最终属性值 4. **自动更新**:每帧更新临时BUFF的剩余时间 **章节来源** - [HeroViewComp.ts](file://assets/script/game/hero/HeroViewComp.ts#L1-L780) ### 技能系统架构分析 最近的代码重构为技能系统添加了ECS注册装饰器,创建了一套完整的技能处理系统。 #### 技能系统组件 ```mermaid classDiagram class CastSkillRequestComp { +number skillIndex +Vec3[] targetPositions +reset() void } class HeroSkillsComp { +Skill[] skills +canCast(index, mp) boolean +getReadySkills(mp) number[] +resetCD(index) void +updateCDs(dt) void } class SkillEnt { +load(startPos, parent, skillId, targets, caster, extraDamage) void } ``` **章节来源** - [HSkillSystem.ts](file://assets/script/game/hero/HSkillSystem.ts#L17-L29) - [HeroSkills.ts](file://assets/script/game/hero/HeroSkills.ts#L1-L200) #### 技能系统层次结构 ```mermaid classDiagram class System { <> +execute(dt) void } class ComblockSystem { +filter() IMatcher +update(entity) void +entityEnter(entity) void +entityRemove(entity) void } class SkillCastSystem { +filter() IMatcher +entityEnter(e) void +checkCastConditions(skillsData, heroModel, skillIndex) boolean +executeCast(casterEntity, skill, targetPositions, heroView) void +createSkillEntity(skillId, caster, targetPositions) void } class SkillCDSystem { +filter() IMatcher +update(e) void } class SkillAutocastSystem { +filter() IMatcher +update(e) void +selectTargets(caster) Vec3[] } System <|-- ComblockSystem ComblockSystem <|-- SkillCastSystem ComblockSystem <|-- SkillCDSystem ComblockSystem <|-- SkillAutocastSystem ``` **章节来源** - [HSkillSystem.ts](file://assets/script/game/hero/HSkillSystem.ts#L47-L271) #### 技能施法流程 ```mermaid sequenceDiagram participant Auto as SkillAutocastSystem participant Cast as SkillCastSystem participant Entity as Entity participant Skill as SkillEnt Auto->>Entity : update() Auto->>Entity : add(CastSkillRequestComp) Cast->>Entity : entityEnter() Cast->>Entity : checkCastConditions() Cast->>Entity : executeCast() Cast->>Entity : playSkillEffect() Cast->>Cast : createSkillEntity() Cast->>Skill : load() Cast->>Entity : remove(CastSkillRequestComp) ``` **图表来源** - [HSkillSystem.ts](file://assets/script/game/hero/HSkillSystem.ts#L47-L171) #### 技能系统功能分析 新的技能系统架构体现了ECS设计的几个关键优势: 1. **职责分离**: - `SkillAutocastSystem`:负责决策"何时施法" - `SkillCastSystem`:负责处理"如何施法" - `SkillCDSystem`:负责管理"技能冷却" 2. **标记驱动设计**: - 使用`CastSkillRequestComp`作为标记组件 - 避免了直接调用系统方法的耦合 - 符合ECS的声明式编程理念 3. **可扩展性**: - 可以轻松添加新的施法策略系统 - 可以复用相同的施法执行逻辑 - 支持玩家输入和AI系统共享同一套施法机制 4. **调试友好**: - 每个系统都有详细的日志输出 - 可以独立启用/禁用调试模式 - 明确的执行流程便于问题排查 **章节来源** - [HSkillSystem.ts](file://assets/script/game/hero/HSkillSystem.ts#L1-L271) ## 性能优化与最佳实践 ### 内存管理策略 ECS框架通过以下机制优化内存使用: ```mermaid flowchart TD Create["创建组件"] --> Pool{"组件池检查"} Pool --> |有可用| Reuse["重用组件实例"] Pool --> |无可用| New["创建新实例"] Reuse --> Use["使用组件"] New --> Use Use --> Remove["移除组件"] Remove --> Reset["reset()重置"] Reset --> Pool Destroy["销毁实体"] --> Clear["清理所有组件"] Clear --> Recycle["回收到池中"] ``` ### 性能优化技巧 1. **组件池化**:避免频繁的垃圾回收 2. **批量处理**:系统一次性处理所有符合条件的实体 3. **条件筛选**:精确的过滤机制减少不必要的遍历 4. **状态缓存**:避免重复计算相同的状态 ### 开发最佳实践 | 实践 | 原则 | 示例 | |------|------|------| | 组件职责单一 | 一个组件只负责一种数据类型 | BattleMoveComp只处理移动相关数据 | | 系统逻辑集中 | 系统处理相关的业务逻辑 | BattleMoveSystem处理所有移动逻辑 | | 避免循环依赖 | 组件间不应有强耦合关系 | 通过系统协调组件交互 | | 合理使用筛选器 | 精确的过滤条件提高性能 | `ecs.allOf(BattleMoveComp, HeroViewComp)` | ## 扩展开发指南 ### 定义新组件 创建新组件的基本步骤: ```typescript // 1. 继承ecs.Comp @ecs.register('NewComponent') export class NewComponent extends ecs.Comp { // 2. 定义组件数据 public data: any; public enabled: boolean = true; // 3. 实现reset方法 reset() { this.data = null; this.enabled = true; } } // 4. 在实体中声明 export class NewEntity extends ecs.Entity { New: NewComponent; } ``` ### 创建新系统 系统开发的标准流程: ```typescript @ecs.register('NewSystem') export class NewSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate { // 1. 定义筛选条件 filter(): ecs.IMatcher { return ecs.allOf(NewComponent, AnotherComponent); } // 2. 实现更新逻辑 update(e: ecs.Entity) { const comp = e.get(NewComponent); const another = e.get(AnotherComponent); // 处理业务逻辑 if (comp.enabled) { // ...具体逻辑 } } } ``` ### 系统接口选择 | 接口 | 用途 | 使用场景 | |------|------|----------| | `ISystemUpdate` | 每帧更新 | 需要持续处理的逻辑 | | `IEntityEnterSystem` | 实体首次进入 | 初始化实体状态 | | `IEntityRemoveSystem` | 实体移除处理 | 清理资源和状态 | | `ISystemFirstUpdate` | 系统首次更新 | 系统初始化逻辑 | | `ISystemDebug` | 调试模式 | 开发阶段的调试信息输出 | **章节来源** - [HSkillSystem.ts](file://assets/script/game/hero/HSkillSystem.ts#L47-L271) - [HeroAtk.ts](file://assets/script/game/hero/HeroAtk.ts#L18-L247) ### 扩展示例 基于现有架构扩展新功能: ```mermaid graph TB subgraph "扩展架构" NewComp["NewComponent
新功能组件"] NewSys["NewSystem
新功能系统"] ExistingComp["ExistingComponent
现有组件"] end subgraph "系统集成" BattleMove["BattleMoveSystem"] NewSys --> BattleMove NewComp --> BattleMove end subgraph "实体组合" Entity["游戏实体"] Entity --> NewComp Entity --> ExistingComp end ``` **章节来源** - [ecs.md](file://doc/ecs/ecs.md#L129-L272) ## 总结 本项目采用的ECS架构展现了现代游戏开发的最佳实践: ### 核心优势 1. **高度模块化**:通过组件组合创建复杂实体 2. **清晰的职责分离**:数据存储在组件,逻辑处理在系统 3. **优秀的性能表现**:批量处理和精确筛选机制 4. **良好的可扩展性**:易于添加新功能和修改现有逻辑 ### 架构特点 - **数据驱动**:系统通过筛选机制处理数据 - **事件驱动**:支持实体进入和移除事件 - **类型安全**:TypeScript提供完整的类型检查 - **内存友好**:组件池化和自动回收机制 ### 应用价值 ECS架构特别适合: - 复杂的游戏AI系统 - 大量相似但行为不同的实体 - 需要高性能处理的游戏逻辑 - 需要频繁扩展和修改的系统 通过深入理解和正确应用ECS架构,开发者可以构建出既高效又易于维护的游戏系统,为玩家提供流畅的游戏体验。