AIGC标识 【游戏架构】【笔记】ECS(Entity Component System)

该文由AI和人工整理获得。

ECS(Entity Component System,实体组件系统) 是一种遵循面向数据设计(Data-Oriented Design, DOD)、合成复用原则(尽量使用组合而不是继承)的软件架构模式。它将“数据”与“逻辑”彻底解耦,通过将同类组件连续存放在内存中来最大化 CPU 缓存命中率,专门用于解决海量同屏实体的性能瓶颈。

简单来说:实体组件系统(ECS)架构将身份(实体entities)、数据(组件components)和行为(系统systems)分开。架构侧重于数据。系统通过读取组件数据流,将数据从输入状态转换为输出状态,这些数据流由实体索引。

核心:实体与组件是一个一对多的关系,实体拥有怎样的能力,完全是取决于其拥有哪些组件,通过动态添加或删除组件,可以在游戏运行时改变实体的行为。

在Unity官方文档中,以下图展示了这三个基本部分如何协同工作:
image

在该图中,系统读取平移和旋转分量,乘以它们,然后更新相应的LocalToWorld分量。

实体A和B有渲染器组件,实体C不会影响系统,因为系统不关心渲染器组件。

总的来说,就是世界中有许许多多个System和Enitity,Enitity中有许许多多个Component。


ECS 基本结构

核心三要素

  • Entity(实体):本质上只是一个全局唯一的 ID,没有任何数据或方法,仅用来标记“哪些组件属于同一个对象”。事实上,就只是一系列组件的集合,所以在运行时动态增加或移除,就可以实现当前不同的状态。
  • Component(组件):纯数据结构(Struct),绝不包含任何逻辑函数(例如 Position { float x, y; }Health { int hp; })。在应用上,比如我们可以运行时动态添加、识别、移除组件,来实现对实体类型的判别。
  • System(系统):纯逻辑行为,自身不保存状态。System 每帧检索出挂载了“特定组件组合”的所有实体,并批量处理数据(例如 MovementSystem 检索同时拥有 PositionVelocity 的实体并更新位置)。

一句话总结:系统从实体的组件中获取数据,并更新组件的状态。

在 Unity 中的内存管理方式

实体的原型决定了该实体组件存储在哪里。一个由ArchetypeChunk对象表示的内存块,总是包含同一原型的实体。如果内存块满了,则会为使用相同原型创建的新实体分配新的内存块。
如果你通过添加或移除组件来更改一个实体原型,该实体的组件会被移到不同的区块

image

这种组织方案为原型和区块之间提供了一对多的关系。这也意味着,找到所有具有特定组成部分的实体只需搜索现有原型,这些原型数量通常较少,而不必搜索所有实体,而实体数量通常远大于此。

注意,实体的组成部分并非按特定顺序存储。当实体被添加到一个原型中时,它会进入该原型中第一个有空间的块。不过,部分区域依然紧凑;当实体从原型中移除时,块中最后一个实体的组件会被移入组件数组中新空出的槽位。

当应用 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 中的包管理器进行检索下载
image


  • 核心组成

    • Unity.Entities:纯正的 Archetype(原型)架构 ECS 框架。
    • C# Job System:用于安全的无锁多线程并行计算。
    • Burst Compiler:将 C# 代码直接编译为经过高度 SIMD 指令集优化的原生机器码。
  • 开发模式

    • 传统模式(GameObject)本质是 OOP 的组件化模型,数据与逻辑混合在 MonoBehaviour 中。
    • 在 DOTS 中,场景内的物体会被 Baker(烘焙器) 转化为无逻辑的 Entity 和纯数据的 IComponentData,再由 ISystemSystemBase 进行批量处理。
  • 引擎定位: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
  • 引擎定位: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)中:

  1. MovementSystem 运行时,CPU 只需要连续读取 PositionVelocity 两个数组。
  2. 连续的内存使得 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

posted @ 2026-09-07 11:04  SEHOD  阅读(45)  评论(0)    收藏  举报