中EN
概念页

MassEntity 数据导向框架

MassEntity Framework

更新于 2026-10-13 约 9 分钟UE5MassECS数据导向FragmentArchetypeProcessor

MassEntity 是 UE5 面向玩法的数据导向 (Data-Oriented) 计算框架,属于实体-组件-系统 (Entity Component System, ECS) 一类设计:实体 (Entity) 只是一个 ID 加上一组片段 (Fragment) 数据,相同组成的实体归入同一原型 (Archetype) 并按内存块 (Chunk) 连续存放,无状态的处理器 (Processor) 通过实体查询 (EntityQuery) 批量处理片段。它适合成千上万个同质对象(人群、交通),MassGameplay 插件在其上提供表现、生成、LOD、复制、StateTree 等功能。

核心概念

概念官方定义要点类比
片段 (Fragment)计算用的原子数据,如 Transform、Velocity、LOD IndexECS 的 Component
实体 (Entity)一组片段的实例,关联一个 ID;由片段组合而成,组成可在运行时改变只有 ID 的对象
原型 (Archetype)组成完全相同的实体集合,如 [Transform, Velocity]一张“表”的列结构
内存块 (Chunk)原型内实体的内存组织单位,保证同原型片段读取性能最佳表的分页
处理器 (Processor)无状态类,提供逻辑;用 EntityQuery 声明所需片段,按批处理而不关心单个实体 IDECS 的 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 这类设计同样值得注意(推论)。

  1. MassEntity Overview & MassGameplay Overview UE 5.8 文档
  2. Game_Engine_Architecture_4th_Edtion_Volume_2_-_Jason_Gregory.pdf
  3. Jason Gregory《Game Engine Architecture》第 4 版(2026)卷 II 第 17 章 17.2.1.6 节
  4. Jason Gregory《Game Engine Architecture》第 4 版(2026)卷 II 第 17 章 17.2.2 节

相关页面

游戏开发多线程渲染与任务系统Multithreaded Rendering & Task SystemsCPU 时钟频率约在 2003 年停在 3.4 GHz 附近后,性能来自多核。应用阶段的优化一是让代码与内存访问更缓存友好,二是利用多核:多处理器流水线(时间并行,提高吞吐但增加延迟)、并行处理(空间并行,延迟更低)以及两者结合的任务系统;图形 API 用命令缓冲让多个线程并行录制绘制命令,新一代 API(DirectX 12、Vulkan、Metal)把更多责任交给应用以降低驱动开销。游戏开发 · UE5Gameplay 框架Gameplay FrameworkGameplay 框架 (Gameplay Framework) 是 UE 提供的一组相互配合的类,用来搭建游戏的基本结构:Actor 与组件 (Component) 构成场景中的一切;GameMode 在服务器上定规则并生成玩家;玩家由“控制器 (Controller) + 棋子 (Pawn)”组成;GameState 与 PlayerState 负责把全局与每个玩家的状态复制给所有客户端;GameInstance 跨关卡存活。游戏开发 · UE5UObject 与反射系统UObject & Reflection System虚幻引擎 (Unreal Engine) 的对象基类是 UObject。在 C++ 类、属性、函数上加 UCLASS/UPROPERTY/UFUNCTION 等宏,再由构建前的预处理工具虚幻头文件工具 (Unreal Header Tool, UHT) 扫描头文件生成代码,引擎就能在运行时“看见”这些类型——这就是反射系统 (Reflection System)。垃圾回收、序列化、编辑器面板、蓝图、网络复制都建立在它之上。游戏开发 · UE5网络复制与 RPCNetwork Replication & RPCUE 采用服务器权威 (Server-Authoritative) 的客户端-服务器模型:游戏真正在服务器上进行,服务器把状态复制 (Replication) 给客户端,客户端通过远程过程调用 (Remote Procedure Call, RPC) 向服务器请求操作。开发者需要显式声明哪些 Actor、属性、函数要走网络,并借助所有权、网络角色、相关性、优先级控制“发给谁、发多少”。UE 5.8 提供通用复制系统、Replication Graph 和实验性的 Iris 三套复制系统。游戏开发 · UE5世界分区World Partition世界分区 (World Partition) 是 UE5 的自动数据管理与基于距离的关卡流送 (Level Streaming) 系统:整个世界存为一个持久关卡,按可配置的运行时网格划分为单元格 (Cell),由流送源 (Streaming Source,默认是玩家控制器) 按距离加载/卸载。它配合一 Actor 一文件 (One File Per Actor, OFPA) 支持多人协作编辑,用数据层 (Data Layers) 按玩法状态切换内容,用分层细节层次 (Hierarchical Level of Detail, HLOD) 在远处以代理网格显示未加载的单元格。图形学细节层次Level of Detail细节层次 (LOD) 在物体对图像贡献变小时改用更简单的表示。LOD 系统由三部分组成:生成(简化或手工制作多个版本)、选择(按距离、投影面积等收益函数挑选)、切换(尽量减少跳变 popping)。LOD 主要减少顶点处理,也通过减少 quad 过度着色降低像素开销;进一步还可在预算约束下全局选择 LOD,实现时间关键(恒定帧率)渲染。游戏开发 · UE5行为树与 StateTreeBehavior Tree & StateTreeUE 的 AI 决策有两套工具:行为树 (Behavior Tree) + 黑板 (Blackboard) 是事件驱动的,条件写成装饰器 (Decorator),用 Simple Parallel、Services 和 Observer Aborts 代替传统并行节点;StateTree 是结合了行为树选择器和状态机转换的通用分层状态机,只在转换触发时按需选择状态,激活路径上的任务并发运行,通过属性绑定传递数据,也是 Mass 的行为层。优先级抢占多的战斗 AI 适合行为树,状态显式、分层或大规模的场景适合 StateTree。游戏开发组件模式Component Pattern组件模式 (Component Pattern) 让一个实体横跨多个领域(输入、物理、图形、AI……),同时不让这些领域彼此耦合:每个领域的代码放进自己的组件类,实体本身退化为组件的容器。它是现代引擎实体模型的基础,代价是对象变成需要正确装配的一组对象,组件之间如何通信也成了要做的设计决策。游戏开发数据局部性Data Locality数据局部性 (Data Locality) 是一种优化思路:CPU 读取内存时会把相邻的一整条缓存行一起载入,所以把数据按处理顺序连续存放,就能大幅减少缓存未命中。具体手段包括:组件按类型存进连续数组,不再到处跟随指针;把活跃对象排在前面;把冷热数据拆开。代价是要放弃一部分继承、接口与指针带来的抽象。游戏开发游戏世界与游戏对象Game World & Game Objects游戏由玩法 (gameplay) 而不是技术定义;游戏机制 (game mechanics) 是支配游戏中各实体交互的规则,以及目标、成败标准、玩家能力、非玩家实体和整体流程(GEA 引用的论文称实现玩法的软件系统为游戏的 G 因子)。大多数游戏世界由静态元素和动态元素组成,划分为若干世界块,并由高层游戏流程组织玩家目标;动态元素通常实现为游戏对象 (GO),引擎提供的建模设施称为游戏对象模型,且分为工具侧和运行时两套(GEA4 卷 II 16、16.1–16.2)。游戏开发运行时对象模型架构Runtime Object Model Architectures玩法基础系统 (gameplay foundation system) 是位于"引擎与游戏分界线"附近、供构建游戏规则和动态元素的一组运行时组件,其中最复杂的是运行时对象模型:它在运行时实现世界编辑器展示给策划的抽象对象模型。GEA 把架构分为两大类:以对象为中心(每个工具侧对象对应一个或一小组类实例)和以属性为中心(对象只是一个 id,属性分散在按属性类型划分、以 id 为键的表里)。前者从单体类层次走向组合与组件,后者更省内存、更缓存友好、更易数据驱动,但难以表达属性间关系、也更难调试(GEA4 卷 II 17.1–17.2)。游戏开发游戏对象并发更新Concurrent Game Object Updates游戏对象模型要和几乎必然是多线程的底层子系统打交道,所以对象代码必须异步思考:耗时操作用非阻塞请求尽早发起、尽晚取结果,必要时容忍一帧延迟。作业之间的依赖决定了并行度 (DOP),每个依赖都引入同步点,"优化并发设计的秘诀是延迟"。对象模型本身也能并行:Naughty Dog 在把引擎从 PS3 移植到 PS4(《最后生还者 重制版》)时,让每个桶内的对象更新成为作业;桶间访问无需加锁,桶内读取用对象快照,桶内修改尽量避免,或加锁、或放进请求队列、或交给下一桶中的同步作业(GEA4 卷 II 17.7)。游戏开发事件队列Event Queue事件队列 (Event Queue) 用一个先进先出队列,把“发送消息或事件”和“处理它”在时间上解耦:发送方入队后立即返回,接收方在自己方便的时候再取出处理。它比观察者和命令模式多做的一件事是时间上的解耦,适合“推”与“拉”两端节奏不同的场合(例如音频请求),代价是全局可见、世界状态可能已经改变,以及可能出现隐蔽的反馈回环。综合游戏编程模式选型:解耦与性能Choosing Game Programming Patterns本页把《Game Programming Patterns》里的 19 个模式放到同一张取舍图上:大多数模式要么为了解耦(降低改代码时需要装进脑子里的知识量),要么为了性能(利用对数据和硬件的具体假设),而这两个目标经常互相拉扯。下面先讲全书的定位和 Nystrom 的架构观,再给出按问题选模式的路线和与 UE 的对照。

输入关键词开始搜索

滚轮或双指缩放 · 拖动平移 · 双击放大 / 还原