【游戏架构】【笔记】ECS(Entity Component System)
该文由AI和人工整理获得。
ECS(Entity Component System,实体组件系统) 是一种遵循面向数据设计(Data-Oriented Design, DOD)、合成复用原则(尽量使用组合而不是继承)的软件架构模式。它将“数据”与“逻辑”彻底解耦,通过将同类组件连续存放在内存中来最大化 CPU 缓存命中率,专门用于解决海量同屏实体的性能瓶颈。
简单来说:实体组件系统(ECS)架构将身份(实体entities)、数据(组件components)和行为(系统systems)分开。架构侧重于数据。系统通过读取组件数据流,将数据从输入状态转换为输出状态,这些数据流由实体索引。
核心:实体与组件是一个一对多的关系,实体拥有怎样的能力,完全是取决于其拥有哪些组件,通过动态添加或删除组件,可以在游戏运行时改变实体的行为。
在Unity官方文档中,以下图展示了这三个基本部分如何协同工作:

在该图中,系统读取平移和旋转分量,乘以它们,然后更新相应的LocalToWorld分量。
实体A和B有渲染器组件,实体C不会影响系统,因为系统不关心渲染器组件。
总的来说,就是世界中有许许多多个System和Enitity,Enitity中有许许多多个Component。
ECS 基本结构
核心三要素
- Entity(实体):本质上只是一个全局唯一的 ID,没有任何数据或方法,仅用来标记“哪些组件属于同一个对象”。事实上,就只是一系列组件的集合,所以在运行时动态增加或移除,就可以实现当前不同的状态。
- Component(组件):纯数据结构(Struct),绝不包含任何逻辑函数(例如
Position { float x, y; }或Health { int hp; })。在应用上,比如我们可以运行时动态添加、识别、移除组件,来实现对实体类型的判别。 - System(系统):纯逻辑行为,自身不保存状态。System 每帧检索出挂载了“特定组件组合”的所有实体,并批量处理数据(例如
MovementSystem检索同时拥有Position和Velocity的实体并更新位置)。
一句话总结:系统从实体的组件中获取数据,并更新组件的状态。
在 Unity 中的内存管理方式
实体的原型决定了该实体组件存储在哪里。一个由ArchetypeChunk对象表示的内存块,总是包含同一原型的实体。如果内存块满了,则会为使用相同原型创建的新实体分配新的内存块。
如果你通过添加或移除组件来更改一个实体原型,该实体的组件会被移到不同的区块。

这种组织方案为原型和区块之间提供了一对多的关系。这也意味着,找到所有具有特定组成部分的实体只需搜索现有原型,这些原型数量通常较少,而不必搜索所有实体,而实体数量通常远大于此。
注意,实体的组成部分并非按特定顺序存储。当实体被添加到一个原型中时,它会进入该原型中第一个有空间的块。不过,部分区域依然紧凑;当实体从原型中移除时,块中最后一个实体的组件会被移入组件数组中新空出的槽位。
当应用 ECS 时
当应用 ECS 时,观察前面的解耦状态,就易发现,由于代码逻辑分布在不同的系统上,而系统之间为了解耦又不能互相访问,当有多个系统希望运行同样的逻辑,该怎么办呢?
可以使用UtilityFunction(实用函数),就像一个方法合集,各个系统都调用其里面的方法,就能统一逻辑了。
同系统一样,UtilityFunction不能存放状态。
Unity 的 ECS:DOTS (Data-Oriented Technology Stack)
曾经,Unity 没有这个 ECS 框架,当时大家使用的是大佬开源的 Entitas 插件,不过现在 Unity 已经更新出 DOTS 了,就让我们来看看吧。
Unity 的 DOTS(数据定向技术栈),是为了彻底解决传统 GameObject + MonoBehaviour 性能开销大、CPU 缓存命中率低的问题。
如何给 Unity 装上这全新的先进框架呢,可以进入这个官方手册查看——Unity ECS packages
简单来说,可以在 Unity 中的包管理器进行检索下载

-
核心组成:
- Unity.Entities:纯正的 Archetype(原型)架构 ECS 框架。
- C# Job System:用于安全的无锁多线程并行计算。
- Burst Compiler:将 C# 代码直接编译为经过高度 SIMD 指令集优化的原生机器码。
-
开发模式:
- 传统模式(
GameObject)本质是 OOP 的组件化模型,数据与逻辑混合在MonoBehaviour中。 - 在 DOTS 中,场景内的物体会被 Baker(烘焙器) 转化为无逻辑的
Entity和纯数据的IComponentData,再由ISystem或SystemBase进行批量处理。
- 传统模式(
-
引擎定位:Unity 允许你完全使用 DOTS 编写整个游戏,也可以在普通
GameObject场景中通过 SubScene(子场景)局部混合使用 ECS。
Unreal Engine 的 ECS:MassEntity 框架
虚幻引擎的核心依然是基于面向对象(OOP)的 Actor-Component 模型(AActor + UActorComponent)。UE5 引入的 MassEntity(Mass 框架) 并非为了替代 AActor,而是作为处理海量同型单位的专用子系统。
注:当前该功能还是实验性的。
官方文档:Mass Entity in Unreal Engine
-
核心概念:
- Fragment:对应 ECS 中的 Component(纯数据结构,如位置、速度)。
- Processor:对应 ECS 中的 System(批量执行逻辑)。
- Trait:将若干 Fragment 和 Processor 组合成某种行为模板的配置工具。
-
混合渲染与代理转换(Representation):
- 远处的成千上万个 NPC/车辆仅作为极低消耗的
Mass Entity存在,使用 ISM(Instanced Static Mesh)进行高性能渲染。 - 当玩家靠近某个 NPC 时,Mass 框架会自动将其平滑替换/升格为包含完整 Blueprint、动画蓝图和碰撞体能力的传统
AActor。
- 远处的成千上万个 NPC/车辆仅作为极低消耗的
-
引擎定位:UE 的核心 Gameplay(如玩家控制器、技能系统 GAS、高级 AI 行为树)依然全盘构建在
AActor之上。MassEntity 主要用于解决人群(Crowd)、车流(Traffic)、集群避障、大型环境质点模拟等场景。
Unity DOTS 与 UE MassEntity 深度对比
| 对比维度 | Unity (DOTS / Entities) | Unreal Engine (MassEntity) |
|---|---|---|
| 引擎定位 | 全局性架构升级(可独立构建完整游戏) | 专项扩展插件(辅助 AActor 处理海量实体) |
| 底层开发语言 | C#(通过 Burst 编译为高性能 Native 机器码) | C++ |
| 术语对应 | Entity / Component (IComponentData) / System |
Entity / Fragment (或 Tag) / Processor |
| 多线程/硬件加速 | Burst Compiler + C# Job System | C++ SIMD + Unreal Task Graph |
| 典型应用案例 | 《V Rising》(吸血鬼崛起)、《海岛大亨6》、海量弹幕/割草游戏 | 《Matrix Awakens》(黑客帝国:觉醒)城市人群与车流 |
| 与传统框架融合 | 通过 SubScene 与 Baker 实现转换 | 通过 Mass Actor / Trait 模块实现混合与距离升级 |
总结
- Unity 走的是“自顶向下的架构重构”路线,试图让开发者逐渐习惯用纯数据驱动(ECS)来构建游戏的核心逻辑。
- UE 走的是“实用主义的局部补充”路线,保持
AActor在复杂 gameplay 和蓝图工作流上的统治地位,只在需要同屏上万个 Agent 时交由MassEntity托管。
ECS 和 OOP
OOP 与 ECS 的核心差异
| 维度 | 传统 OOP (如 Unity MonoBehaviour / UE Actor) | ECS 架构 (如 Unity DOTS / Flecs) |
|---|---|---|
| 设计理念 | 基于继承与封装("Dog 继承自 Animal") | 基于数据组合("Entity 组合了 DogData") |
| 数据与逻辑 | 强绑定(类中既有属性又有 Update 方法) | 彻底解耦(数据在 Component,逻辑在 System) |
| 内存分布 | 对象散落分配于堆(Heap),指针跳转导致高 Cache Miss | 同类 Component 连续紧密存储(SoA 内存布局) |
| 多线程支持 | 对象间状态交织,多线程锁争用剧烈 | System 纯逻辑且数据独立,天然适配 Job System |
ECS 极高性能的底层原理
传统 OOP 采用 AoS(Array of Structures) 模式,遍历对象时会顺便把无关数据(如渲染、音效等指针)加载进缓存,导致 CPU L1/L2 缓存利用率低下。
现代 ECS 普遍采用 Archetype(原型) 或 Chunk 内存管理,将拥有相同组件集合的实体放在同一个连续内存块(SoA, Structure of Arrays)中:
- 当
MovementSystem运行时,CPU 只需要连续读取Position和Velocity两个数组。 - 连续的内存使得 CPU 硬件预取器(Hardware Prefetcher)能精准将下一批数据提前载入缓存,几乎消除了 CPU 等待内存读取的瓶颈。
选型建议
- 适合使用:同屏海量单位(如割草游戏、RTS 军队、弹幕、物理/粒子仿真、大型地图网格数据)。
- 不适合使用:UI 系统、复杂的单体主角/BOSS 控制器(状态特异性高,数据组合复用率低)、需要快速开发验证的重剧情/轻量游戏。
[1] Unity. ECS concepts[EB/OL]. https://docs.unity3d.com/Packages/com.unity.entities@0.1/manual/ecs_core.html
[2] 杨睿涵. 游戏开发中的ECS 架构概述[EB/OL]. (2018.05.01). https://zhuanlan.zhihu.com/p/30538626

浙公网安备 33010602011771号