Search Unity

How to appropriately use the EntityCommandBuffer?

Discussion in 'Data Oriented Technology Stack' started by cjddmut, Dec 14, 2019.

  1. cjddmut

    cjddmut

    Joined:
    Nov 19, 2012
    Posts:
    120
    I'm trying to have actions queued up to be processed at the end up the update tick instead of at the beginning of the update tick. However, trying to use EndSimulationEntityCommandBufferSystem's buffer causes an exception to be thrown.

    Here's the simple test I wrote that shows how I'm using to use the EntityCommandBuffer and this script is also resulting in the exception.


    Code (CSharp):
    1. using Unity.Collections;
    2. using Unity.Entities;
    3. using Unity.Jobs;
    4. using UnityEngine;
    5.  
    6. public class TestCmdBuffer : MonoBehaviour
    7. {
    8.     private World _world;
    9.    
    10.     private void Start()
    11.     {
    12.         _world = new World("Test");
    13.  
    14.         SimulationSystemGroup g = _world.CreateSystem<SimulationSystemGroup>();
    15.         g.AddSystemToUpdateList(_world.CreateSystem<CmdSystem>());
    16.  
    17.         _world.EntityManager.CreateEntity(typeof(TestComp1));
    18.         _world.Update();
    19.         _world.EntityManager.CompleteAllJobs();
    20.     }
    21.  
    22.     private void OnDestroy()
    23.     {
    24.         _world.Dispose();
    25.     }
    26. }
    27.  
    28. public class CmdSystem : JobComponentSystem
    29. {
    30.     protected override JobHandle OnUpdate(JobHandle inputDeps)
    31.     {
    32.         // Throw an ArgumentException, doesn't if I use the BeginSimulationEntityCommandBufferSystem but I want the comp
    33.         // to show up during this tick, not before the next tick
    34.         EndSimulationEntityCommandBufferSystem ecbSystem =
    35.             World.GetExistingSystem<EndSimulationEntityCommandBufferSystem>();
    36.  
    37.         AddCompJob job = default;
    38.         job.cmdBuffer = ecbSystem.CreateCommandBuffer().ToConcurrent();
    39.  
    40.         return job.Schedule(this, inputDeps);
    41.     }
    42.  
    43.     private struct AddCompJob : IJobForEachWithEntity<TestComp1>
    44.     {
    45.         public EntityCommandBuffer.Concurrent cmdBuffer;
    46.        
    47.         public void Execute(Entity entity, int index, [ReadOnly] ref TestComp1 c0)
    48.         {
    49.             cmdBuffer.AddComponent<TestComp2>(index, entity);
    50.         }
    51.     }
    52. }
    53.  
    54. public struct TestComp1 : IComponentData
    55. {
    56.    
    57. }
    58.  
    59. public struct TestComp2 : IComponentData
    60. {
    61.    
    62. }
    Notably if I use BeginSimulationEntityCommandBufferSystem instead then I do not get the error but then the buffer isn't processed until the next tick.

    Tips?
     
  2. Creepgin

    Creepgin

    Joined:
    Dec 14, 2010
    Posts:
    362
    You need to
    cmdBuffer.AddJobHandleForProducer(handle);
    before returning. This lets the barrier know which jobs to complete before ECB playbacks.

    May also wanna cache the ecbSystem in OnCreate instead of OnUpdate.
     
    Last edited: Dec 14, 2019
    cjddmut likes this.
  3. cjddmut

    cjddmut

    Joined:
    Nov 19, 2012
    Posts:
    120
    Perfect, easy! That was it.

    Thanks!