ECS框架文档翻译十 Entity Command Buffer

以下文档均来源于ECS官网:

https://docs.unity3d.com/Packages/[email protected]/manual/ecs_entities.html

Entity Command Buffer(实体命令缓存)

EntityCommandBuffer 类解决了两个重要问题:

  1. 当在Job中时,无法访问EntityManager
  2. 当您访问EntityManager (比如说,修改一个实体)时,这将使所有与该实体关联的数据数组和EntityQuery对象无效

我们把实体命令缓存(EntityCommandBuffer)这个概念抽象出来,为了是允许您对实体或者组件的修改(来自作业或主线程)进行队列缓存,以便它们后续可以在主线程上得以执行。有两种方法来使用EntityCommandBuffer:

在主线程上更新ComponentSystem的子类时,有现成的PostUpdateCommands成员变量可以调用。 使用它来修改属性,这些修改将会以命令的形式被到缓存队列。 当从System的Update方法返回后,它们将会被立刻应用到当前的World。

Here's an example:

PostUpdateCommands.CreateEntity(TwoStickBootstrap.BasicEnemyArchetype);
PostUpdateCommands.SetComponent(new Position2D { Value = spawnPosition });
PostUpdateCommands.SetComponent(new Heading2D { Value = new float2(0.0f, -1.0f) });
PostUpdateCommands.SetComponent(default(Enemy));
PostUpdateCommands.SetComponent(new Health { Value = TwoStickBootstrap.Settings.enemyInitialHealth });
PostUpdateCommands.SetComponent(new EnemyShootState { Cooldown = 0.5f });
PostUpdateCommands.SetComponent(new MoveSpeed { speed = TwoStickBootstrap.Settings.enemySpeed });
PostUpdateCommands.AddSharedComponent(TwoStickBootstrap.EnemyLook);

如您所见,此API与EntityManager的API非常相似。 在这种模式下,EntityCommandBuffer将显得非常方便,它可以帮助您防止系统内部的数组失效{译者注:当Entity发生变化时,它的多个ComponenentData会发生迁移,所以那些处于其它系统Job内并行访问此ComponentData的数组引用将失效},同时仍然可以对世界进行更改。

对于在Job中的情况,您需要从主线程上的EntityCommandBufferSystem请求EntityCommandBuffer ,让后将它们传递给Job。 当EntityCommandBufferSystem更新时,CommandBuffer将按照它们被创建的顺序在主线程上顺序执行。 由于这种附加的处理步骤,可以使得内存管理得以集中,并且可以保证实体和组件生成的确定性。

让我们再来看两个例子,看看它在具体事件中是如何运作的。

Entity Command Buffer Systems(实体命令缓存系统)

默认的World初始化提供了三个system组,分别用于初始化,模拟和显示,它们每帧将会按顺序更新。 在每一个组内,均存在2个实体命令缓存系统(EntityCommandBufferSystem),一个在组中其它所有的系统之前运行,而另一个在组中的所有其他系统之后运行。 你最好直接使用现成的EntityCommandBufferSystem,而不是创建自己的命令缓存系统,以便最小化同步点。 有关默认组和命令缓存系统的列表,请参见Default System Groups 。

在ParallelFor jobs中使用EntityCommandBuffers

在从ParallelFor jobs作业中,使用EntityCommandBuffer发出EntityManager命令时,EntityCommandBuffer.Concurrent接口用于保证线程安全性和后续执行的确定性。 此接口中的public方法额外采用了一个jobIndex参数,该参数用于以确定的顺序来执行已经被记录的命令。 作为每个作业的ID,jobIndex必须是唯一的。 出于性能原因,jobIndex应该直接使用系统传递给IJobParallelFor.Execute()方法index值(此值是自增的) 。 除非你真的知道你在做什么,否则使用这个index作为jobIndex是最安全的选择。 使用其他jobIndex 值也将产生正确的输出,但在某些情况下会产生严重的性能影响。

你可能感兴趣的:(Unity中的ECS编程)