ECS 架构模式

ECS怎么重新被发现的

几年前,守望先锋团队在GDC上做分享的时候,向大家安利了一发如何利用 Entity-Component-System 架构简化开发难度、提高效率的。这里有一些讨论:

如何评价《守望先锋》中的架构设计(ECS)? https://www.zhihu.com/question/61169850

然后业内就像商量好了似的,大家都站出来夸ECS,Unity甚至表示要将整个引擎架构和工作流往ECS上迁移,作为其 Performance by Default 的宏大计划中的重要组成部分。自此,ECS开始了全面大讨论,各类博客文章如雨后春笋般涌现。

本文作为一个漫谈而不是技术手册的语调,来说说ECS有啥好处、有啥不足。游戏服务端的同学也可以看一看,毕竟ECS的大体思想和微服务有几分相似。

面向数据 vs 面向对象

ECS是一种以面向数据(DOD,Data Oriented Design)的架构。这里先简单说一下面向对象和面向数据两种设计思路。

OOP (面向对象编程)是我们对现实世界的简单抽象,非常易于理解。但是,在大型项目中,往往并不是最好的解决方案,因为OOP:

  • 并不是CPU友好的。OOP中的对象往往很臃肿,但有时只需要访问其中一个或少量几个数据,但如果要加载整个对象进cache,这很浪费。

  • 数据分散在对象中,不易管理。

DOD (面向数据设计)则是cache友好的,但不是那么符合直觉中好的设计。

  • cache友好可以这么理解:N个对象,每个对象有M个成员,每个对象可表示为 Mx1的矢量。那么这些数据排成一个矩阵。则OOP是对矩阵按列分(供N列),而DOD是按行分(共M行)。显然DOD对cache更友好。

  • 一般需要框架去支持,不然写起来不方便。

这些年似乎越来越多人开始觉得面向对象编程不够好(不够时尚),函数式编程才是本质(酷)。表面上看,ECS多少也借了这股风迎来自己的春天。其实是以下内在原因:

  • 现代游戏的重点和复杂性逐渐转移到数据密集型计算和渲染上来了。ECS保持了DOD对cache友好的优点,性能提升突出。

  • 游戏设计需求变化频繁,需要做大量的快速原型来验证玩法,而面向对象这种scheme太强了,很难提前设计一个很好的OOP结构。而不好的OOP结构对一个复杂项目而言,是一种灾难。

总之,面向数据和面向对象都是杰出的思考框架,而且一定程度上并不矛盾,可以分别以不同模块的形式存在于我们的游戏工程中(比如UI部分还是面向对象比较方便)。

ECS架构精髓(TODO)

Entity: 只是一个带有 ID 的容器,容纳若干Component

Component: 只有数据,没有逻辑。

System: 没有数据(状态),只有逻辑。一个System只关心自己需要的数据,通过遍历这些数据,来进行逻辑处理。

ECS好在哪里(TODO)

  • 速度。因为cache友好。

  • 解耦。

  • 组件复用方便,没有副作用。

ECS麻烦在哪里(TODO)

  • 物理。

  • 多个System的协同。

  • 编辑器下游戏场景不直观。

结语

ECS对性能的提升是毋庸置疑的,不过其对于工程架构的想法很美好,实操起来会有其它问题要处理。因为复杂度只是被转移了,“脏”的东西依然存在。我们要做的是,把这些脏的东西放在一起,并以可控、可寻的方式来管理。没有一劳永逸的方法,关键的还是团队中的“人”。

Last updated