Component-Based Architecture(组件化架构)
核心概念(简洁定义)
-
Entity(实体) :场景中的对象容器(例如
GameObject/Actor),持有组件集合并代表一个"游戏对象"实例。 -
Component(组件):附属于实体的模块化单元,负责局部数据与行为。组件可以包含状态与行为(与严格 DOTS 的纯数据不同)。
-
System(系统) :负责驱动组件和实体的逻辑单元。可以实现为
Manager、Service、Subsystem等,通常按预定义顺序执行以保证时序可控。
特点
-
高内聚、低耦合:每个系统 / 实体 / 组件只负责自己的逻辑。
-
明确的执行时序:系统与实体组件的执行顺序通过枚举/列表定义,便于控制与调试。
ex : SystemOrder { Res, Config, Scene, Data, Actor, AI, Physics, Skill, View, UI, }
ex : ComponentOrder { Model, Locomotion, Animation, Skill, Buff, State, Event, View }
-
Hybrid/可渐进迁移:既能使用 MonoBehaviour 做编辑器/交互,也能用纯代码的 Manager 做驱动逻辑。
生命周期
System 生命周期(全局/Manager)
-
Awake():资源/配置加载、静态注册(启动前,仅执行一次)。 -
StartGame():局内初始化(每场/每次运行时调用)。 -
UpdateBefore()/Update()/UpdateAfter():按顺序执行的帧更新(若需要细分可用 Before/After)。 -
FixedUpdate():物理步或固定步逻辑。 -
LateUpdate():渲染/视图同步相关的后置更新。 -
EndGame():局内结束,清理临时数据/事件监听。 -
Reset():彻底重置到初始状态(用于回到菜单或完全销毁前)。
Entity / Actor 生命周期(单个实例)
-
Awake():只做与配置无关的内部初始化(构造时、注册事件)。 -
Start():读配置、创建组件实例、建立依赖(当实体"生效"时调用)。 -
Born():出生时的触发逻辑(播放出生动画、发事件)。 -
Update()/LateUpdate()/FixedUpdate():按组件/系统驱动的帧更新。 -
Dead():死亡处理(广播死亡事件、掉落、禁用行为)。 -
Recycle()(抽象):把实例/组件重置到可复用状态,清理引用,返回对象池。 -
Destroy():彻底销毁,释放资源(与 Recycle 不同,通常不可复用)。
UML

@startuml
' Title
title ECS-like / Component-Based Architecture (简化类图)
' 基础类
class Entity <<MonoBehaviour>> {
}
class Actor {
- ActorConfig data
- string customTag
+ Initialize()
+ AddComponent(ActorComponent)
}
Actor --|> Entity
class ActorComponent {
- Actor owner
+ OnAwake()
+ OnUpdate()
}
' 具体组件
class ActorStats {
- Dictionary<StatType, StatValue> stats
+ GetStat(StatType)
}
ActorStats --|> ActorComponent
class ActorActiveSkill {
- List<SkillInstance> skills
}
ActorActiveSkill --|> ActorComponent
' Managers / Systems
class ManagerComponent {
- ManagerType type
+ OnStart()
+ OnUpdate()
}
class Managers {
- List<ManagerComponent> managers
+ UpdateAll()
}
Managers "1" o-- "*" ManagerComponent : manages
class ScenesManager {
}
ScenesManager --|> ManagerComponent
class ActorManager {
}
ActorManager --|> ManagerComponent
' 关系
Actor "1" *-- "*" ActorComponent : contains
ActorComponent --> Actor : owner
@enduml
常见问题与防护建议
-
事件重复/广播重复
-
问题:事件重复触发/生命周期外触发。
-
解决:统一事件总线
EventBus,并在实体回收/死亡时统一注销。对频繁注册/注销的场景使用弱订阅或带listenerId的显式注册以便快速移除。Recycle()必须释放所有事件订阅。
-
-
组件之间耦合过高
- 防护:所有跨组件调用通过接口或 Manager 转发。
-
内存泄漏与 GC 压力
-
防护:避免频繁 new/alloc(每帧 new string、临时 delegate 等),使用对象池(实体/子弹/skillInstance)、Native 集合或复用数组。
-
Recycle()必须释外部引用
-
-
Update 顺序不确定
-
防护:把系统顺序显式化(如
SystemOrder枚举)并由Managers按序调用; -
实体内部组件也明确插槽/序号,避免隐式依赖。
-
-
逻辑分散到 UI / View
- 防护:把纯逻辑留在系统/组件层,View 只负责展示;双向同步使用单向数据流(系统 -> view 更新,UI 操作为 command 发回 Manager 处理)。
命名与约定(团队一致性建议)
-
系统:
XyzManager/XyzSystem(例如SpawnManager,SkillManager) -
组件:
XxxComponent(例如StatsComponent,BuffComponent) -
生命周期方法统一使用
OnAwake/OnStart/OnUpdate/OnRecycle/OnDestroy -
枚举/优先级:
SystemOrder,Components明确注释和版本兼容(方便插入新阶段)
测试 / 调试 / 质量保障
-
为关键 System 和 Component 写单元测试(用接口注入与 Mock)------例如
SkillManager.Execute(skill, actor)的纯逻辑可单测。 -
在编辑器中实现
DebugMode:打印系统执行顺序、组件 attach/detach 日志、泄漏检测(未注销监听器警告)。 -
使用 Profiler 找热点(不要盲目迁移到 ECS;只优化确实成为瓶颈的子系统)。