ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

ECS的概念

2022-07-10 00:32:44  阅读:382  来源: 互联网

标签:实体 系统 概念 原型 内存 组件 ECS


ECS架构分离了身份(实体),数据(组件)和行为(系统)。这个架构聚焦于数据。系统(Systems)会读取组件数据流,之后将数据从输入状态转换到输出状态,之后对实体进行索引。

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

img

在这个图中,系统会先读取Translation和Rotation两个组件,将二者相乘然后更新相应的LocalToWorld组件(LocalToWorld=T*R)

实体A和B有一个Renderer组件,而实体C没有。这并不会影响到系统,因为系统不关心Renderer组件。

你可以设置一个需要Renderer组件的系统,这样系统会忽略C的组件;或者,你可以设置一个系统来排除带有Renderer组件的实体,这样就会忽略实体A和B的组件。

Archetypes(原型)

组件类型唯一的组合被称作EntityArchetype。例如,一个3D对象可能有用于在世界中变换的组件、用于线性运动的组件,用于旋转的组件、用于视觉表示的组件。这些3D对象的每个实例对应一个单独的实体,但是因为他们共享相同的组件集合,ECS会将他们归为同一个原型。

img

在这个图中,实体A和B共享了原型M,而实体C拥有原型N。

如果要平滑的改变实体的原型,可以通过在运行时增加或删除组件。例如,如果你删除实体B中的Renderer组件,它会自动转移到原型N

编辑器中的原型

你可以在Archetypes window这一编辑器中,看到如下的图标表示一个原型

image-20220709033051517

Memory Chunks(内存块)

实体的原型决定了ECS将该实体的组件存储在哪里。ECS会以 ArchetypeChunk结构的形式分配内存,每个块由一个原型对象来表示。块总是包含单一的原型实体。当一个内存块被填满时,ECS会分配新的内存给相同原型创建的新实体。如果你增加或删除组件导致改变实体原型,ECS会将该实体的组件移动到不同的内存块中。

img

这种组织模式提供了原型和内存块之间的一对多的关系,这也意味着找到具有一定给定组件的所有实体,只需要搜索现有的原型。这样搜索数量会很小,而不是通过搜索所有的实体,这样搜索量会减少很多。

ECS不以特定的顺序存储内存块中的实体。当一个实体被创建或者改变到一个新的原型时,ECS会将它放入到第一个存储原型的并且还有空间的内存块中。然而块仍然是紧密堆积在一起的;当一个实体从原型中被删除时,ECS会移动最后一个实体的组件进入到组件数组中新空出的插槽中。

  • NOTE:原型中共享的组件的值也决定了哪些实体被存储到哪些块中,对于任何共享组件,给定内存块中的所有实体都具有完全相同的值。如果你修改共享组件中任何领域内的值,修改后的实体会移动到不同的内存块中,就如同你改变实体的原型一样,如果需要也会分配到一个新的内存块。

使用共享组件对原型中的实体分组可以更有效率的将这些程序一起启动。例如Hybrid Renderer定义了它的RenderMesh组件去实现这一点。

实体的查询

要确定哪些实体是系统需要处理的,可以使用 EntityQuery结构。实体查询在现有原型中搜索拥有匹配需求的组件的原型。你可以用一个查询来指定以下组件需求:

ALL——原型必须包含ALL类别的所有组件类型

Any——原型必须包含Any类别中至少一种组件类型

None——原型不能包含None类别中的任何组件类型

实体查询提供了一个包含查询需要的所有类型的组件的列表。然后你可以用 IJobEntityBatch直接遍历这些块中的组件。

Jobs

为了充分利用多线程,你可以使用C# Job system。ECS提供了SystemBase类和Entities.ForEach和IJobEntityBatchSchedules()和ScheduleParalle()方法,用于在主线程之外转换数据。Entities.ForEach是最容易使用并且通常需要更少的代码来实现。你可以在Entities.ForEach无法处理的复杂情况下使用IJobChunk来处理。

ECS按照系统安排的顺序在主线程调度jobs,在调度jobs的时候,ECS会记录哪些jobs读取和写入哪些组件。一个读取组件的job依赖于任何一个之前写入相同组件的调度job,反之亦然。job调度器使用job以来关系来确定哪些可以并行运行,哪些job必须按顺序运行

系统组织

ECS按照 Worldgroup来组织系统。默认情况下,ECS按照预定义的group集合来创建一个默认的世界。它找到了所有可用的系统并且实例化他们,然后增加他们到默认World中的预定义的simulation group 中。

你可以指定同一组中系统的更新顺序,组是一种系统所以你可以增加一个组到另一个组并且指定他们的顺序,就像任何其他系统一样所有在同一组内的系统会在下一个系统或组之前更新。如果不指定顺序,ECS会不依赖于创建顺序的确定性方式将系统插入到更新顺序中。换句话说,即使您没有显式地指定顺序,同一组系统也总是以相同的顺序更新。

系统更新发生在主线程上,然而系统会利用jobs来将工作分配到其他线程上。SystemBase 提供了一种直接的方式来创建和调度jobs

想要查找更多关于系统创建(system creation)、更新顺序(update order)和你可以用来组织你系统的属性( attributes you can use to organize your systems)的信息,你可以查看 System Update Order 文档。

ECS authoring(创作)

当你在Unity中创建游戏或者应用时,你可以利用GameObject和MonoBehaviours来创建一个转换系统(conversion system)来映射这些UnityEngine对象和组件到实体中。更多信息请查看 Creating Gameplay文档。

标签:实体,系统,概念,原型,内存,组件,ECS
来源: https://www.cnblogs.com/onehow/p/16460162.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有