Files
pixelheros/.qoder/repowiki/zh/content/技术架构/ECS架构.md
panw b38e63e200 refactor(skill): 重构技能组件目录结构并重命名施法请求组件
将技能相关组件从hero目录移动到skill目录
将CastSkillRequestComp重命名为CSRequestComp
更新相关引用和文档说明
2025-10-31 09:22:50 +08:00

18 KiB
Raw Blame History

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注册装饰器的更改
  • 添加了关于技能系统的新部分包括CSRequestComp、SkillCastSystem、SkillCDSystem和SkillAutocastSystem
  • 更新了实际案例分析,以包含新的技能系统实现
  • 在扩展开发指南中添加了新的系统接口示例
  • 更新了文档来源以包含新分析的文件

目录

  1. 简介
  2. ECS架构概述
  3. 组件系统详解
  4. 实体生命周期管理
  5. 系统架构与执行机制
  6. 实际案例分析
  7. 性能优化与最佳实践
  8. 扩展开发指南
  9. 总结

简介

ECSEntity-Component-System是一种流行的游戏架构模式它通过将数据与行为分离来实现高度模块化和可扩展的系统设计。本项目采用TypeScript版本的ECS框架实现了游戏逻辑的数据与行为解耦为复杂的游戏系统提供了清晰的架构基础。

ECS架构概述

核心概念

ECS架构由三个核心元素组成

graph TB
subgraph "ECS架构核心"
Entity["实体 (Entity)<br/>唯一标识符"]
Component["组件 (Component)<br/>数据容器"]
System["系统 (System)<br/>逻辑处理器"]
end
subgraph "交互关系"
Entity --> Component
System --> Entity
System -.-> Component
end
subgraph "执行流程"
System --> Filter["筛选机制"]
Filter --> Entities["符合条件的实体"]
Entities --> Update["系统更新"]
end

图表来源

架构优势

  1. 数据与行为分离:组件只存储数据,系统处理逻辑
  2. 高度模块化:通过组合不同组件创建复杂实体
  3. 性能优化:批量处理相同类型的操作
  4. 易于扩展:新增功能只需添加新组件和系统

组件系统详解

组件注册机制

组件通过装饰器@ecs.register进行注册框架自动管理组件的生命周期和内存回收。最近的代码重构为多个英雄系统添加了ECS注册装饰器使架构更符合标准。

classDiagram
class Component {
<<abstract>>
+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

图表来源

组件添加与移除机制

组件的添加和移除遵循严格的生命周期管理:

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.Entity创建,并支持父子实体关系管理:

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>() 从实体池中获取或创建新实体
添加组件 entity.add(Component) 优先从组件池获取,否则创建新实例
移除组件 entity.remove(Component) 组件重置后放回组件池
销毁实体 entity.destroy() 清理所有组件并回收实体
子实体管理 addChild(Entity) 管理实体间的父子关系

章节来源

系统架构与执行机制

系统层次结构

classDiagram
class System {
<<abstract>>
+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

图表来源

筛选机制

系统通过filter()方法筛选符合条件的实体:

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([完成])

图表来源

系统执行流程

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详细分析

BattleMoveSystem展示了ECS架构在游戏AI中的应用

组件依赖关系

graph LR
Entity["游戏实体"] --> BattleMoveComp["BattleMoveComp<br/>移动控制"]
Entity --> HeroViewComp["HeroViewComp<br/>视图控制"]
BattleMoveComp --> Direction["direction<br/>移动方向"]
BattleMoveComp --> TargetX["targetX<br/>目标位置"]
BattleMoveComp --> Moving["moving<br/>移动状态"]
HeroViewComp --> HP["hp/mp<br/>生命值"]
HeroViewComp --> Status["status<br/>状态"]
HeroViewComp --> Position["node.position<br/>位置信息"]

图表来源

系统更新逻辑

BattleMoveSystem的核心更新逻辑体现了ECS的优势

  1. 数据分离:移动逻辑完全封装在系统中
  2. 条件筛选只处理同时拥有BattleMoveComp和HeroViewComp的实体
  3. 状态管理:根据游戏状态动态调整行为
  4. 性能优化:只处理活跃实体,避免不必要的计算

关键算法实现

算法 功能 实现位置
敌人检测 检查攻击范围内是否有敌人 checkEnemiesInRange()
最近敌人查找 寻找最近的敌对单位 findNearestEnemy()
位置验证 验证移动位置的有效性 validatePosition()
渲染层级更新 根据位置更新渲染顺序 updateRenderOrder()

章节来源

HeroViewComp综合组件分析

HeroViewComp展示了组件如何存储复杂的游戏状态

属性管理系统

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 : 管理

图表来源

BUFF系统架构

HeroViewComp实现了复杂的BUFF/DEBUFF管理系统

  1. 持久BUFF:存储在BUFFS数组中,永久存在直到手动移除
  2. 临时BUFF:存储在BUFFS_TEMP数组中,带有剩余时间
  3. 属性计算根据数值型和百分比型BUFF计算最终属性值
  4. 自动更新每帧更新临时BUFF的剩余时间

章节来源

技能系统架构分析

最近的代码重构为技能系统添加了ECS注册装饰器创建了一套完整的技能处理系统。

技能系统组件

classDiagram
class CSRequestComp {
+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
}

章节来源

技能系统层次结构

classDiagram
class System {
<<abstract>>
+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

章节来源

技能施法流程

sequenceDiagram
participant Auto as SkillAutocastSystem
participant Cast as SkillCastSystem
participant Entity as Entity
participant Skill as SkillEnt
Auto->>Entity : update()
Auto->>Entity : add(CSRequestComp)
Cast->>Entity : entityEnter()
Cast->>Entity : checkCastConditions()
Cast->>Entity : executeCast()
Cast->>Entity : playSkillEffect()
Cast->>Cast : createSkillEntity()
Cast->>Skill : load()
Cast->>Entity : remove(CSRequestComp)

图表来源

技能系统功能分析

新的技能系统架构体现了ECS设计的几个关键优势

  1. 职责分离

    • SkillAutocastSystem:负责决策"何时施法"
    • SkillCastSystem:负责处理"如何施法"
    • SkillCDSystem:负责管理"技能冷却"
  2. 标记驱动设计

    • 使用CSRequestComp作为标记组件
    • 避免了直接调用系统方法的耦合
    • 符合ECS的声明式编程理念
  3. 可扩展性

    • 可以轻松添加新的施法策略系统
    • 可以复用相同的施法执行逻辑
    • 支持玩家输入和AI系统共享同一套施法机制
  4. 调试友好

    • 每个系统都有详细的日志输出
    • 可以独立启用/禁用调试模式
    • 明确的执行流程便于问题排查

章节来源

性能优化与最佳实践

内存管理策略

ECS框架通过以下机制优化内存使用

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)

扩展开发指南

定义新组件

创建新组件的基本步骤:

// 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;
}

创建新系统

系统开发的标准流程:

@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 调试模式 开发阶段的调试信息输出

章节来源

扩展示例

基于现有架构扩展新功能:

graph TB
subgraph "扩展架构"
NewComp["NewComponent<br/>新功能组件"]
NewSys["NewSystem<br/>新功能系统"]
ExistingComp["ExistingComponent<br/>现有组件"]
end
subgraph "系统集成"
BattleMove["BattleMoveSystem"]
NewSys --> BattleMove
NewComp --> BattleMove
end
subgraph "实体组合"
Entity["游戏实体"]
Entity --> NewComp
Entity --> ExistingComp
end

章节来源

总结

本项目采用的ECS架构展现了现代游戏开发的最佳实践

核心优势

  1. 高度模块化:通过组件组合创建复杂实体
  2. 清晰的职责分离:数据存储在组件,逻辑处理在系统
  3. 优秀的性能表现:批量处理和精确筛选机制
  4. 良好的可扩展性:易于添加新功能和修改现有逻辑

架构特点

  • 数据驱动:系统通过筛选机制处理数据
  • 事件驱动:支持实体进入和移除事件
  • 类型安全TypeScript提供完整的类型检查
  • 内存友好:组件池化和自动回收机制

应用价值

ECS架构特别适合

  • 复杂的游戏AI系统
  • 大量相似但行为不同的实体
  • 需要高性能处理的游戏逻辑
  • 需要频繁扩展和修改的系统

通过深入理解和正确应用ECS架构开发者可以构建出既高效又易于维护的游戏系统为玩家提供流畅的游戏体验。