Programming/ECS -1.0

EntityCommandBuffer

Inner-Peace 2023. 1. 5. 14:15
반응형

멀티스레드 환경에서 하나의 데이터에 변경 작업을 하면 경쟁 문제가 발생한다.

그래서 멀티스레드 환경에서 원활하게 변경 작업을 할 수 있도록  만든것.

 

EntityCommandBuffer는 작업 큐에 저장을 해두고 해당 프레임이 완료되면 큐에 저장된 버퍼들을 처리되도록 함.

 

단일 스레드에서 사용법

// ... in a system update

// You don't specify a size because the buffer will grow as needed.
EntityCommandBuffer ecb = new EntityCommandBuffer(Allocator.TempJob);

// The ECB is captured by the ForEach job.
// Until completed, the job owns the ECB's job safety handle.
Entities
    .ForEach((Entity e, in FooComp foo) =>
    {
        if (foo.Value > 0)
        {
            // Record a command that will later add
            // BarComp to the entity.
            ecb.AddComponent<BarComp>(e);
        }
    }).Schedule();

this.Dependency.Complete();

// Now that the job is completed, you can enact the changes.
// Note that Playback can only be called on the main thread.
ecb.Playback(this.EntityManager);

// You are responsible for disposing of any ECB you create.
ecb.Dispose();

동시에 작업하려면

 

// ... in a system update

EntityCommandBuffer ecb = new EntityCommandBuffer(Allocator.TempJob);

// We need to write to the ECB concurrently across threads.
EntityCommandBuffer.ParallelWriter ecbParallel = ecb.AsParallelWriter();

// The entityInQueryIndex is unique for each entity and will be
// consistent for each particular entity regardless of scheduling.
Entities
    .ForEach((Entity e, int entityInQueryIndex, in FooComp foo) => {
        if (foo.Value > 0)
        {
            // The first arg is the 'sort key' recorded with the command.
            ecbParallel.AddComponent<BarComp>(entityInQueryIndex, e);
        }
    }).Schedule();

// Playback is single-threaded as normal.
this.Dependency.Complete();

// To ensure deterministic playback order,
// the commands are first sorted by their sort keys.
ecb.Playback(this.EntityManager);

ecb.Dispose();

EntityCommandBuffer를 여러번 사용하는 방법

PlaybackPolicy.MultiPlayback 을 붙여줘야 한다 ( 안붙여주면 오류 )

// ... in a system update

EntityCommandBuffer ecb =
        new EntityCommandBuffer(Allocator.TempJob, PlaybackPolicy.MultiPlayback);

// ... record commands

ecb.Playback(this.EntityManager);

// Additional playbacks are OK because this ECB is MultiPlayback.
ecb.Playback(this.EntityManager);

ecb.Dispose();

EntityCommandBufferSystem을 사용해서 버퍼를 만들면 실행과 해제를 자동으로 해준다.

public class BufferSystem : EntityCommandBufferSystem 
{
}

기본적인 버퍼 시스템

  • BeginInitializationEntityCommandBufferSystem
  • EndInitializationEntityCommandBufferSystem
  • BeginSimulationEntityCommandBufferSystem
  • EndSimulationEntityCommandBufferSystem
  • BeginPresentationEntityCommandBufferSystem

 

반응형