[Unity ECS]使用 Entity Command Buffers – Unite Copenhagen 2019

Posted u010019717

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[Unity ECS]使用 Entity Command Buffers – Unite Copenhagen 2019相关的知识,希望对你有一定的参考价值。

 

Using Entity Command Buffers – Unite Copenhagen 2019

https://www.youtube.com/watch?v=SecJibpoTYw

https://www.slideshare.net/unity3d/using-entity-command-buffers-unite-copenhagen-2019

 

https://docs.unity3d.com/Packages/com.unity.entities@0.0/api/Unity.Entities.EntityCommandBuffer.html

https://docs.unity3d.com/Packages/com.unity.entities@0.1/manual/entity_command_buffer.html

 

Using Entity Command Buffers – Unite Copenhagen 2019

           并非所有游戏玩法都需要立即发生。 实际上,在许多情况下,延迟命令可能会提供更好的结果–改善用户体验,性能等。这些幻灯片探讨了在何处需要延迟命令的思考,并提供了有关如何充分利用实体命令缓冲区的示例。

Overview

— What are Entity Command Buffers?什么是实体命令缓冲区?

– Recording Commands记录命令

– Playback Order播放顺序

— Command Playback命令播放

– EntityCommandBufferSystems

– Immediate vs Deferred立即与延迟

— Traps to Avoid避免陷阱

— Possible Future Improvements未来可能的改进

 

Problem They Solve他们解决的问题

-Structural changes happen on the Main Thread主线程上发生结构更改

-Solution for recording changes in parallel through Jobs通过Jobs并行记录更改的解决方案

 

这些是什么?

–Chains of data transformations that are recorded记录的数据转换链

–Either from the Main Thread or within Jobs (Concurrent)从主线程中或在Jobs中(并发)

–Played back at a specific point in the future在将来的特定时间回放

–从EntityCommandBufferSystem

 

命令

–一些可用命令

–实例化,创建或销毁实体  Instantiate, Create, or Destroy an Entity

–添加,设置或删除组件数据Add, Set, or Remove Component Data

–向实体添加或设置IBufferElementData    Add or Set IBufferElementData to an Entity

–添加或设置SharedComponent数据     Add or Set SharedComponent Data

–向EntityQuery中的每个实体添加或删除组件   Add or Remove Components to each Entity in an EntityQuery

– 主线程与并发命令        Main Thread vs Concurrent Commands

–主线程:托管数据正常         Main Thread: Managed Data OK

–并发:子集,不允许使用托管数据            Concurrent: Subset with No Managed Data Allowed

 

 

 

Main Thread Chain

— Single chain单链

— Played back in order of recording 按录制的顺序播放

 

Concurrent Chains并发链

— Multiple chains多个链

— Playback in order by JobIndex按JobIndex顺序播放

– JobIndex unique per batch of work  每批工作唯一的JobIndex

— Deterministic确定性

– JobIndex becomes a way to sort commandsJobIndex成为对命令进行排序的一种方式

– Large continuous chunks of monotonically increasing numbers连续大块单调递增的数字

 

Concurrent Chains Recording并发链记录

— Multiple threads recording from Concurrent EntityCommandBuffer to their own chain从并发EntityCommandBuffer记录到自己的链的多个线程

 

 

 

Concurrent Chains Playback (Today)并发链播放(今天)

— Find the batch with the lowest job index 查找job index最低的批次

— Start executing commands linearly until the end of the batch开始线性执行命令,直到批处理结束

— Repeat looking for the next smallest until done重复寻找下一个最小值,直到完成

 

 

 

Command Playback命令播放

Deferred vs Immediate Playback延迟与即时播放

— Deferred

– Scheduling Playback later in another EntityCommandBufferSystem稍后在另一个EntityCommandBufferSystem中安排播放

– Systems already there已经存在的系统

– Example: BeginInitializationEntityCommandBufferSystem示例

— Immediate

– Calling myCommandBuffer.Playback(…) right after recording录制后立即调用myCommandBuffer.Playback(…)

– PostUpdateCommands: Right after System’s Update()    ||PostUpdateCommands:在系统的Update()之后

 

// Taken from SpawnFromEntity example BeginInitializationEntityCommandBufferSystem m_EntityCommandBufferSystem;

protected override void OnCreate()



// 1: Set your command buffer system

m_EntityCommandBufferSystem = World.GetOrCreateSystem<BeginInitializationEntityCommandBufferSystem>();



protected override JobHandle OnUpdate(JobHandle inputDeps) 

// 2: Pass a Concurrent Command Buffer into the job

var job = new SpawnJob  CommandBuffer = m_EntityCommandBufferSystem.CreateCommandBuffer().ToConcurrent() .Schedule(this, inputDeps);

// 3: Add the JobHandle to the Command Buffer System m_EntityCommandBufferSystem.AddJobHandleForProducer(job); return job;

 

示例 RPG 游戏,释放技能施毒,掉血伤害, DPS

Frame0的时候, 玩家对命中的Enemy 

         伤害, 技能, CD 三个系统

 

 

 

 

 

    进入 Frame1 了 

 

 

 

   System Begin 的时候 

 

      Damage系统进行处理

 

 

Traps to Avoid 避免陷阱

Knowing When Data Is Available知道何时有数据

— Important to know when you will need that data to exist重要的是要知道何时需要该数据存在

— Tradeoff: Narrow window for playback vs longer deferment权衡:播放的窗口较窄,延迟时间更长

– Systems running between recording and playback will see the “old” data在录制和播放之间运行的系统将看到“旧”数据

 

Deferred Entities

— Instantiate(…) returns an Entity that’s deferred   实例化(...)返回一个延迟的实体

– It does not exist yet它尚不存在

– Has a negative Entity ID实体ID为负

— During Playback播放期间

– Entity gets a positive ID once it’s created实体创建后会获得一个肯定的ID

– Future references to that Entity in the chain are fixed up修复了链中对该实体的将来引用

 

Storing a Reference to a Deferred Entity ID存储对延迟实体ID的引用

— When your ComponentData stores a reference to some entity that will be created later当您的ComponentData存储对稍后将创建的某些实体的引用时

— That Entity will be invalid!该实体将无效!

 

Too Many Sync Points同步点太多

— Sync points can prevent a lot of work to be done in parallel同步点可能会阻止大量并行工作

— Playing back commands when you need that data在需要该数据时播放命令

— Consolidate those points to specific times in the frame将这些点合并到框架中的特定时间

– Use the pre-existing ECB Systems or create your own使用现有的ECB系统或创建自己的ECB系统

 

ECB Invalid After Playback播放后ECB无效

— Once it’s played back, can’t record to it again播放后,无法再次录制

— Error regarding a Native Container有关本机容器的错误

— Create a new ECB创建一个新的ECB

 

Possible Future Improvements 未来可能的改进

Bursted ECB

— Bursted Recording and Bursted Playback突发记录和突发播放

— Recording Available Soon! 即将提供录制!

Bursted ECB Code Example 突发ECB代码示例

// Taken from SpawnFromEntity example

[BurstCompile(CompileSynchronously = true)]

struct SpawnJob : IJobForEachWithEntity<Spawner_FromEntity, LocalToWorld>



public EntityCommandBuffer.Concurrent CommandBuffer;

public void Execute(Entity entity, int index, [ReadOnly] ref Spawner_FromEntity spawnerFromEntity, [ReadOnly] ref LocalToWorld location)



for (var x = 0; x < spawnerFromEntity.CountX; x++)

// CountX = 100  for (var y = 0; y < spawnerFromEntity.CountY; y++)

// CountY = 100  var instance = CommandBuffer.Instantiate(index, spawnerFromEntity.Prefab);

// Place the instantiated in a grid with some noise

var position = math.transform(location.Value, new float3(x * 1.3F, noise.cnoise(new float2(x, y) * 0.21F) * 2, y * 1.3F));

CommandBuffer.SetComponent(index, instance, new Translation Value = position);   CommandBuffer.DestroyEntity(index, entity);   

 

Without Burst (in ms) 0.64 With Burst (in ms)* *Average = 10x speedup 10kEntities

 

Batched Playback批量播放

— Processing certain commands in bulk for better performance批量处理某些命令以获得更好的性能

– Such as Instantiate or AddComponent如实例化或AddComponent

— All playback is still happening on the Main Thread所有回放仍在主线程上进行

 

Entity Manager Feature Parity实体管理器功能奇偶校验

— EntityManager has more options for each functionEntityManager为每个功能提供更多选项

– Such as AddComponent ( NativeArray <Entity>, Component )如

— Would like them to be unified希望它们被统一

 

Review评论

What To Remember要记住什么

— Chains of data transformations数据转换链

— Played back at a specific point in the future在将来的特定时间播放

— Think about the point when you need that data考虑一下何时需要该数据

— No managed data within jobs, therefore no commands with managed data within jobs作业中没有托管数据,因此作业中没有包含托管数据的命令

Thank you!

 

以上是关于[Unity ECS]使用 Entity Command Buffers – Unite Copenhagen 2019的主要内容,如果未能解决你的问题,请参考以下文章

Unity ECS框架入门

unity ECS简介

ET框架学习-ECS组件式编程的基本思想之于UNITY

ECS 系统 Entity-Component-System

关于ECS(Entity-Component-System)游戏编程中数据访问控制的问题

DOTS简介