MassEntity 数据导向框架
MassEntity Framework
MassEntity 是 UE5 面向玩法的数据导向 (Data-Oriented) 计算框架,属于实体-组件-系统 (Entity Component System, ECS) 一类设计:实体 (Entity) 只是一个 ID 加上一组片段 (Fragment) 数据,相同组成的实体归入同一原型 (Archetype) 并按内存块 (Chunk) 连续存放,无状态的处理器 (Processor) 通过实体查询 (EntityQuery) 批量处理片段。它适合成千上万个同质对象(人群、交通),MassGameplay 插件在其上提供表现、生成、LOD、复制、StateTree 等功能。
核心概念
| 概念 | 官方定义要点 | 类比 |
|---|---|---|
| 片段 (Fragment) | 计算用的原子数据,如 Transform、Velocity、LOD Index | ECS 的 Component |
| 实体 (Entity) | 一组片段的实例,关联一个 ID;由片段组合而成,组成可在运行时改变 | 只有 ID 的对象 |
| 原型 (Archetype) | 组成完全相同的实体集合,如 [Transform, Velocity] | 一张“表”的列结构 |
| 内存块 (Chunk) | 原型内实体的内存组织单位,保证同原型片段读取性能最佳 | 表的分页 |
| 处理器 (Processor) | 无状态类,提供逻辑;用 EntityQuery 声明所需片段,按批处理而不关心单个实体 ID | ECS 的 System |
| 标签 (Tag) | 不含数据的片段,“有没有”本身就是数据 | 布尔标记 |
| 块片段 (ChunkFragment) | 关联到 Chunk 而非实体的数据,如 LOD 计算用的每块数据 | 每页共享的头信息 |
| 特征 (Trait) | 提供某项功能的片段 + 处理器的集合,如避障、注视目标、StateTree | “能力包” |
片段与实体都是纯数据、不含逻辑。(MassEntity Overview & MassGameplay Overview)
下图展示数据与逻辑的关系:多个实体按组成归入原型,原型数据分块存放;处理器只通过查询声明需要哪些片段,然后成批遍历匹配的块。
flowchart LR
subgraph A1["原型 Transform+Velocity"]
C1["Chunk 1:实体 0..n 的连续片段"]
C2[Chunk 2]
end
subgraph A2["原型 Transform+Velocity+Tag_Enemy"]
C3[Chunk 1]
end
P["移动处理器<br/>Query: Transform 可写, Velocity 只读"] --> C1
P --> C2
P --> C3
P -. "结构变更" .-> CB["MassCommandBuffer<br/>批末统一执行"]图中处理器同时匹配两个原型,因为两者都含所需片段;对实体增删片段会改变原型,因此通过命令缓冲延后执行。(MassEntity Overview & MassGameplay Overview)
为什么这样设计:数据布局与批处理
官方指出顺序(串行)处理片段是操作实体最高效的方式,原型按块组织正是为了让同原型片段的读取性能最好。(MassEntity Overview & MassGameplay Overview)这背后是缓存友好的数据布局——同类数据连续存放,遍历时预取命中率高;与之相对,每个 Actor 是一个分散在堆上的 UObject,带有虚函数、组件和反射开销(见 UObject 与反射系统、Gameplay 框架)。并行与数据导向的更多背景见 多线程渲染与任务系统。
两个关键机制(MassEntity Overview & MassGameplay Overview):
- MassCommandBuffer:处理器可以增删片段或标签,但在处理过程中改组成会把实体从一个原型挪到另一个原型;因此结构变更以命令形式提交,在当前批处理结束时统一执行。
- EntityView:需要访问当前未在处理队列中的其他实体时,用 EntityView 安全且优化地读取。
子系统与配置
MassEntity 的各子系统都是世界子系统 (World Subsystem),生命周期绑定所在 World。MassEntity Manager 是最重要的部分:创建并托管原型,提供增删片段等实体操作,负责在原型间移动实体,其他子系统可经命令缓冲异步调用。实体模板 (Entity Template) 由编辑器中的 MassEntityConfig 资产生成,资产声明一组特征,并可继承父资产的特征。(MassEntity Overview & MassGameplay Overview)
MassGameplay:从数据到游戏世界
| 子系统 | 作用 |
|---|---|
| Mass Representation | 按表现 LOD 选择高精度 Actor、低精度 Actor、实例化静态网格 (ISM,可用顶点动画驱动,实验性) 或不表现,处理切换并池化回收 Actor |
| Mass Spawner | 通过放置 MassSpawner Actor + 实体定义资产 + 分布生成器生成实体 |
| Mass LOD | 输出 High/Medium/Low/Off 四级(及 0.0–3.0 的重要度),可按距离和每级最大数量配置 |
| ├ 表现 LOD | 结合距离与视锥判断可见性 |
| ├ 模拟 LOD (Simulation LOD) | 对计算做负载均衡,同 LOD 实体归入同块,支持可变更新频率 |
| └ 复制 LOD (Replication LOD) | 按每个连接的观察者计算相关性,节省带宽 |
| Mass Replication | 服务器到客户端单向复制,实验性,自定义数据需 C++ |
| Mass StateTree | 为实体配置 StateTree;StateTree 只设置数据,使正确的处理器运行 |
| Mass Signals | 向实体发送无载荷的命名信号;框架以“拉取”模式为主,信号用于唤醒处理 |
| Mass Movement / SmartObject | 简单移动模型(速度/力可被避障等叠加修改);与 SmartObject 集成 |
(MassEntity Overview & MassGameplay Overview)
表现层“近处用 Actor、远处用 ISM、再远不显示”是 细节层次 在实体层面的应用;复制 LOD 与通用复制系统中按连接计算相关性的思想一致,见 网络复制与 RPC。开放世界中的人群通常与 世界分区 一起使用。
取舍
下表中 MassEntity 一列来自官方文档,Actor 一列的开销描述为一般性对比说明。
| 维度 | MassEntity | 传统 Actor |
|---|---|---|
| 数量级 | 面向大量同质实体 | 数量多时 CPU 与内存开销大 |
| 数据布局 | 按原型分块连续,批处理 | 每对象独立分配 |
| 逻辑组织 | 无状态处理器 + 查询 | 面向对象,逻辑在类里 |
| 编辑与调试 | 官方提供专门的 Mass Debugger | 编辑器、蓝图工作流成熟 |
| 网络 | Mass Replication 仍为实验性 | 成熟的 Actor 复制 |
| 结构变更 | 需经命令缓冲延迟执行 | 随时增删组件 |
实践中常见做法是“混合”:大量远处或简单个体由 Mass 模拟,近处需要完整交互的个体通过 Representation 切换为真正的 Actor。本次抓取的官方页面没有给出性能数值或基准数据,因此本页不引用具体数字。
GEA 的视角:以属性为中心的对象模型(卷 II 17.2.1.6、17.2.2)
GEA 第 17 章描述的两种架构与 MassEntity 的设计直接相关,详见 运行时对象模型架构:
- 纯组件模型:去掉
GameObject枢纽,对象只剩一个 id,组件按 id 逻辑分组;GEA 列出的难点是如何为每种类型创建正确的组件组合(工厂或数据驱动)以及组件间、对象间如何通信。 - 以属性为中心:每种属性一张表、以对象 id 为键,像关系数据库;行为由对象拥有的属性集合隐式决定。GEA 列出的优点是省内存(只存实际用到的属性)、易于数据驱动、同类型数据连续存放更缓存友好(SoA 布局,GEA 举例 PS3 上一次缓存未命中相当于执行数千条指令);缺点是难以强制属性间关系、难以由细粒度属性拼出大尺度行为、调试时不能一眼看到一个对象的全部状态。
与本页对照:MassEntity 的"实体 = ID + 片段""相同组成的实体归入同一原型并按 Chunk 连续存放""无状态处理器按查询批量处理",属于 GEA 说的纯组件/以属性为中心一端,并把 GEA 的 SoA 思路落实为按原型分块的内存布局(对比归纳)。GEA 提到的调试困难,对 Mass 这类设计同样值得注意(推论)。
出处
- MassEntity Overview & MassGameplay Overview UE 5.8 文档
- Game_Engine_Architecture_4th_Edtion_Volume_2_-_Jason_Gregory.pdf
- Jason Gregory《Game Engine Architecture》第 4 版(2026)卷 II 第 17 章 17.2.1.6 节
- Jason Gregory《Game Engine Architecture》第 4 版(2026)卷 II 第 17 章 17.2.2 节