关于Unity 2018的实体组件系统(ECS)一

孙广东  2018.5.19html

 

 

首先来自ECS的概念。git

 

什么是ECS?github

首先什么是ECS? ECS是一种新的架构模式(只是在Unity中算新)。网络

总之,这是一个(做为目标)取代GameObject / Component 的模式。 其模式遵循组合优于继承原则,游戏内的每个基本单元都是一个实体,每一个实体又由一个或多个组件构成,每一个组件仅仅包含表明其特性的数据(即在组件中没有任何方法)。系统即是来处理拥有一个或多个相同组件的实体集合的工具,其只拥有行为(即在系统中没有任何数据)。架构

实体与组件是一个一对多的关系,实体拥有怎样的能力,彻底是取决于其拥有哪些组件,经过动态添加或删除组件,能够在(游戏)运行时改变实体的行为。工具

 

ECS旨在比GameObject / MonoBehaviour更容易处理大量物体。性能

 

ECS的特色是,因为面向数据的设计 , 很容易并行高速处理,和 C# Job System 一块儿工做。测试

 

Unity技术演示, 移动大量对象优化

 

启用Burst编译器时的性能差别,能够与ECS结合使用动画

 

 

如今已经提供了只有基本功能。例如没有刚体系统或动画系统,甚至没有体面的渲染器。大多数实现须要由你本身完成。

可是,若是功能可用,性能比GameObject好 。

 

 

顺便说一句,配合C# Job System, 可使CPU利用率接近100% 。

 

 

如下是 (未优化) 性能结果比较。 传统的脚本OC, C# Job System, Entity Component System, 和ECS with Burst Compiler。测试从1.3万对象到6.8万个。

 

 

 

 

ECS术语

ECS有几个术语。

例如,实体Entity,组件数据Component Data,组件系统ComponentSystem,组Group 等4项。

  • 实体Entity:像容器同样
  • 组件数据Component Data:要存储在实体中的数据(不包括处理)
  • 组件系统ComponentSystem:处理
  • 组Group:组件系统运行所需的ComponentData列表

 

还有不少其余的东西,可是目前这四个内容最重要。

 

它与 起源(传统)ECS术语略有不一样。

  • Entity=Entity
  • ComponentData =Component
  • ComponentSystem = System

 

 

在这个术语中,与Unity的GameObject /Component相比,有一个稍微接近的地方。若是彻底粗略地说明,则它与如下项目匹配。

 

  • Entity=GameObject
  • ComponentData =Component的字段
  • ComponentSystem =Component的Update方法
  • Group = 无

 

 

 

ECS与Component结合使用

Unity的GameObject和Component, 经过给GameObject 提供MonoBehaviour 来定义行为。有一种状况是使用一个Manager,并指示他们移动的功能

 

此外, 会有移动角色的组件。

例如,当一个名为Move的组件移动时,Move组件是经过GetComponent访问Transform获得并移动该对象。

 

 

另外一方面,ECS的工做就是这样:

  • ECS的行为 (System系统)和数据 (Component组件)将分别实现。
  • Entity实体中存储了多种类型的数据(Component组件)。
  • 若是存储在对象(实体)中的数据(组件)知足本组请求的数据列表,则调用行为(系统)。

 

MonoBehaviour有1:1的数据和处理,但在ECS中它处理的是 ComponentData的组合。

例如,ComponentData有Transform和 Move做为一组,并经过Group请求系统进行移动 。

 

处理时,称为变换和移动的组件信息直接传递到系统。

 

像这样,调用什么样的处理由System(和Group)的组合来决定,实体是在全部系统来匹配批处理。

以下表所示,可能很容易理解哪一种处理将起做用。

 

不管如何,ECS被定义为ComponentData的组合......

 

补充

首先是实体,这是从EntityManager生成的。建议从头开始使用ComponentData生成实体,但您能够稍后添加它。

实体在游戏中有不少像GameObject同样的东西。在某种意义上,实体≈游戏对象。

 

系统为每一个实体执行处理。像下图所示 。

在两个系统的状况下,若是组匹配,都会工做。这可能在一个线程中运行,有时由C# Job System并行化。

 

 

例1

 

例如,让咱们考虑一个实体,它具备在碰到障碍物时简单的前向右转的功能。

考虑到表示此实体所需的ComponentData,它以下所示。

  • 坐标
  • 前方障碍的距离
  • 运动方向

顺便说一句,若是你想用这个参数来实现运动,能够考虑下面的实现。

一、从“坐标coordinates”和“运动方向direction”中查找“到前方障碍物的距离distance and obstacle 

二、若是“前方障碍物Obstacles in front of”小于某个值,则更改“移动方向direction of movement

三、沿“移动方向movement”方向移动“坐标coordinate

 

 

我把它们放入系统中。

系统负责实现 检查距离,更新方向, 更新坐标。 由于这些都是行为!!!!!

 

 

 

示例问题2

那么,此次你想让一个实体像“朝指定坐标方向移动”那样?

 

这个实体彷佛有如下ComponentData。

  • 坐标
  • 指定坐标
  • 运动方向

系统看起来像。

一、从指定坐标坐标中寻找移动方向

二、在移动方向的方向上移动坐标

 

那么,这是第二个系统,使用与例1中彻底相同的东西。 因为请求组是相同的。

若是你很好地理解系统,系统在很大范围内是很好的,可是它也使得实现更加麻烦。彷佛有必要考虑这里的平衡。

 

 

ComponentData组合的补充

它是ComponentData的组合,但实际上能够设置多个组。

例如,建立GameObjectEntity(只有一个)和Unit Entity(有不少)的组合,你能够期待的十日或一次所有中止根据游戏管理的状况下该股的操做。

 

另外,ComponentData不包含任何特别的内容,它有时指定ComponentData仅做为组的定义, 做为一个熊。

例如,若是你想有一个特殊处理,“熊猫”和“熊”是熊,须要PandaComponentData出现。

 

 

您能够对ComponentData进行添加,删除,设置(覆盖?)操做。也有点像游戏对象

 

 

 

 

 

谁调用了ComponentSystem?

到目前为止,有一点有趣的是“谁调用系统?”

定义后自动调用!!!!!应该是世界在调用吧1

可是调用顺序,你也能够控制。

 

 

 

 

 

 

 

 

实体之间的消息传递

实体之间的消息交换是不可能的。

 

若是要将消息发送到特定实体,而后用实体内容覆盖ComponentData,则系统处于处理中。

 

 

 

 

 

 

补充

ECS并非面向对象的,因此不能很好地理解,并试图在OOP的背景下去理解(经验

“不知何故FOWA!好像不可能理解”,你可能期待着面向数据的设计,并且可能会更好。

 

  • 观察者模式,能够被用于在系统间发送事件。
  • 策略模式,算是ECS模式的基石。

 

 

 

其它连接 能够更好的了解:

官方开源, 也有文档可也查阅!

相关文章
相关标签/搜索