Unity ECS 01 核心概念

原文:https://docs.unity3d.com/Packages/com.unity.entities@0.11/manual/ecs_core.html

ECS 组件

实体组件系统(ECS)架构将身份(实体),数据(组件)和行为(系统)分开。 该架构专注于数据。 系统读取组件数据流,然后对数据进行处理,将其从输入状态转换为输出状态,然后对这些实体进行索引(没看懂)。

下图说明了这三个基本部分如何协同工作:

原图
在此图中,系统读取Translation和Rotation组件,将它们相乘(L2W = T * R),然后用结果更新相应的LocalToWorld组件。
虽然实体A和B具有Renderer组件,而实体C没有。但是C不会影响系统,因为这个系统不关心Renderer组件。
您可以设置一个系统,使它需要一个渲染组件,在这种情况下,系统就会忽略实体C的组件;或者,您可以设置一个系统来排除具有渲染组件的实体,这样就忽略实体A和B上的组件。

原型

组件的不同组合方式称为原型。 例如,一个3D对象可能具有一个表示位置的组件,一个表示运动的组件,一个表示旋转的组件和一个用于渲染的组件。 每个这种3D对象都对应一个实体,但是由于它们共享相同的组件集,因此ECS将它们归类为同一个原型:

原图
在此图中,实体A和B共享原型M,而实体C具有原型N。
为了顺利更改实体的原型,可以在运行时添加或删除组件。 例如,如果您从实体B中删除了Renderer组件,则它的原型就变成了N。

内存块

实体的原型决定ECS在何处存储该实体的组件。 ECS以“块”分配内存,每个块均由一个ArchetypeChunk对象表示。 一个块始终包含同一原型的实体。 当一个块满了之后,ECS会为同一原型创建的任何新实体分配新的块。 如果添加或删除组件,导致实体原型改变了,则ECS会将该实体的所有组件移动到其他块中。

原图
这种组织模式在原型和块之间提供了一对多的关系。这还意味着,要找到具有某些组件的所有实体,只需要搜索所有的原型(通常数量较少),而不是搜索所有实体(通常数量更多)。
ECS不以特定的顺序存储块中的实体。当实体被创建或更改原型时,ECS将其放入该原型的第一个有空余空间的块中。然而,块仍然是紧密排列的:从某个块中删除实体时,ECS将块中最后一个实体移动到空出的槽中。
具有共享组件的实体也决定着这些实体存储在哪个块中。同一块中的所有实体对于任何共享组件都具有完全相同的值。 如果更改共享组件中任何字段的值(从而不再与其他实体共享这个值),则修改后的实体将移至其他块,就像更改该实体的原型时一样。 如有必要,就分配新的块。
当一起处理实体的效率更高时,可以使用共享组件对原型中的实体进行分组。例如,Hybrid Renderer定义了RenderMesh组件来实现这一点。

实体查询

要确定系统应该处理哪些实体,请使用EntityQuery。实体查询在原型中搜索具有所需要组件的原型。您可以进行如下查询:

  • All: 原型必须包含所有指定的组件。
  • Any:原型必须包含至少一个指定的组件。
  • None:原型不能包含任何指定的组件。
    实体查询会返回符合需求的的块列表。然后可以使用IJobChunk直接迭代这些块中的组件即可。

任务(job)

要利用多个线程,可以使用[C#Job system]。 ECS提供SystemBase类以及Entities.ForEachIJobChunk.Schedule()ScheduleParallel()方法,以将数据传递到主线程之外。 Entities.ForEach是最简单的使用方法,通常只需较少的代码即可实现。 您可以用IJobChunk处理那些Entities.ForEach无法处理的更复杂的情况。
ECS按照你的系统所安排的顺序在主线程上调度job。 在调度完job后,ECS会跟踪哪些job对哪些组件进行了读取和写入。 读取组件的job依赖于那些必须在这次读取前对该组件进行写入job,反之亦然。 job调度程序使用job的依赖性来确定哪些job可以并行,哪些必须按顺序运行。

对系统的管理(System organization)

ECS先通过世界,然后通过组来管理系统(system)。 默认情况下,ECS将使用一些预定义的组来创建一个默认世界。 它找到所有可用的系统,实例化它们,并将它们添加到默认世界中的预定义的模拟组中。
您可以指定一个组中对每个系统进行更新的顺序。 组本身也是一种系统,因此您可以像其他系统一样将组添加到另一个组中并指定其顺序。 当前组中的所有系统会在下一个系统或组之前进行更新。 如果未指定顺序,则ECS将指定一种确定的顺序,而这种顺序与创建系统的顺序是无关的。 换句话说,即使您未明确指定顺序,组内的每个系统也会以相同顺序进行更新。
系统的更新在主线程上进行。 但是,系统可以使用job将工作分流到其他线程。 SystemBase提供了创建和调度作业的直接方法。
更多信息参考:组件更新顺序

当你在Unity编辑器中创建你的游戏或应用程序时,你可以使用GameObjects和monobehavior来创建一个转换系统来将那些UnityEngine对象和组件映射到实体。有关更多信息,请参见创建Gameplay

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
 一: 什么是ECS?       ECS是一种新的架构模式(当然是针对Unity本身来说),这是一个取代GameObject / Component 的模式。 其模式遵循组合优于继承原则,游戏内的每一个基本单元都是一个实体,每个实体又由一个或多个组件构成,每个组件仅仅包含代表其特性的数据(即在组件中没有任何方法)。系统便是来处理拥有一个或多个相同组件的实体集合的工具,其只拥有行为(即在系统中没有任何数据)。       ECS旨在比GameObject / MonoBehaviour更容易处理大量物体。ECS由于是面向数据的设计,所以很容易并行高速处理,以及与Unity开发的C#JobSystem/Burst Compiler一起工作,从而获取更高的项目运行性能。二:ECS总体发展历史       目前Unity公司由Mike Acton 大佬主持DOD(Data Oriented Design 面向数据设计)的全面改革与推进工作,目的是旨在进一步推进Unity系统本身与Unity项目的执行效率。    ECS总体发展:    A: 在Unity2018引入Entities之前,其实ECS框架早已经出现,但是ECS还是因为守望先锋采用了这个框架才被我们所熟知,后来Git上面出现了一个Entitas的插件可以直接用在Unity上面。Entitas-Unity(有多个语言的port版本,Entitas-Unity下统一称为Entitas) 是 Unity的一个ECS(Entity/Component/System)框架,是在github上面的一个开源项目。    B: 经过Unity公司的认可与改造,目前Unity2018.x 版本已经通过 Package Manager 提供了Unity版本的ECS插件,名称为:“Entities”。    C: Unity2019.x 版本,对“Entities”插件的API进行了进一步改造与完善,以更规范的API实现更加高效的与规范的编程模式。 三:ECS(一)轻松入门篇       本“ECS入门篇”旨在全面讲解ecs 的相关理论与简单Hello World 的编程模式,且通过Unity2018.x与Unity2019.x 两个不同API的编程模式,初步讲解ECS的编程规范与模式规范。        需要进一步学习ECS的小伙伴们,可以关注后续“ECS(二)小试牛刀”篇的进一步讲解。   《Unity ECS(二) 小试牛刀》https://edu.csdn.net/course/detail/27096 

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值