Search Unity

Create CommandBuffer sync point in JobComponentSystem

Discussion in 'Data Oriented Technology Stack' started by calabi, Aug 10, 2019.

  1. calabi

    calabi

    Joined:
    Oct 29, 2009
    Posts:
    84
    I'm wondering if there is a way of doing this. I have a JobComponentSystem with 2 jobs which are connected, the first job checks entity's and adds components to some of them. The second Job then checks those entity's to see if some of them have that added component.

    But the code doesn't work because I'm guessing the CommandBuffer adds all the components to the entity's after both of the jobs in the update loop. So is there not a way to create a sync similar to handle.complete() but for CommandBuffers, so that the second Job activates after the CB has completed its thing.
     
  2. Draveler

    Draveler

    Joined:
    Jul 1, 2018
    Posts:
    53
  3. calabi

    calabi

    Joined:
    Oct 29, 2009
    Posts:
    84
    Yeah thanks I was wondering if that was the only way. I have two jobs in the same jobcomponentsytem I was hoping to keep it that way. It just adds more complexity if I have to separate them.
     
  4. ChrisTsu

    ChrisTsu

    Joined:
    Jan 13, 2019
    Posts:
    5
    I'm very new to all this but maybe:
    [UpdateBefore BeginSimulationEntityCommandBufferSystem] , for the system
    and use the BeginSimulationEntityCommandBuffer for the first job
    and EndSimulationEntityCommandBuffer for the second job

    but i think splitting them and do the first system at begin buffer and the second at end buffer is cleaner.
    Again i'm new, take what i say with a grain of salt.
     
  5. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    1,560
    You probably shouldn't update before begin or update after end systems.

    Instead you should just create your own EntityCommandBufferSystem and slot that in the middle.
     
  6. ChrisTsu

    ChrisTsu

    Joined:
    Jan 13, 2019
    Posts:
    5
    oh alright, could you explain me how the begin buffer systems should be used then? i mean what's their purpose? for the next frame? for initialization group systems?
     
  7. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    1,560
    There's no reason you can't use it and it won't cause you any issues, I just feel if you're working within Simulation you should be between the 2 designated start and end buffers. Keeps things organized and consistent and you might avoid some ordering issues in the future.

    That said, how you can use it is you just use it like normal, it lets you not sync your jobs till the start of the next simulation instead of completing at the end. This means your jobs could run during other tasks (such as presentation, legacy monobehaviours etc.) In practice it doesn't really matter a lot of the time though.
     
  8. calabi

    calabi

    Joined:
    Oct 29, 2009
    Posts:
    84
    Thanks for replies. I did look at the EndSimulationEntityCommandBuffer, but to be honest I'm not sure how I would use it in the way you are suggesting. I'm also not sure how I would create a new EntityCommandbuffer and use it to run in the middle. I'll post the code I've got so far.
    Code (CSharp):
    1. public class DeductandApplyWages : JobComponentSystem
    2. {
    3.  
    4.     //private int counter = 0;
    5.     public bool jobcompleteitself;
    6.     EndSimulationEntityCommandBufferSystem m_EntityCommandBufferSystem;
    7.  
    8.     protected override void OnCreate()
    9.     {
    10.         this.Enabled = false;
    11.         m_EntityCommandBufferSystem = World.GetOrCreateSystem<EndSimulationEntityCommandBufferSystem>();
    12.     }
    13.  
    14.     [RequireComponentTag(typeof(Business))]
    15.     struct DeductWagesJob : IJobForEachWithEntity<MoneyEntityInfo>
    16.     {
    17.         //public ComponentDataFromEntity<MoneyEntityInfo> currentcomp;
    18.         public Entity currentent;
    19.         public int GlobalWages;
    20.         public EntityCommandBuffer.Concurrent commandsBuffer;
    21.         //
    22.         public void Execute(Entity ello, int indax,  ref MoneyEntityInfo currentbuswages)
    23.         {          
    24.             int tempvar = currentbuswages.MoneyHeld;
    25.             tempvar -= currentbuswages.Wages;
    26.             if (tempvar < 0)
    27.             {
    28.                 commandsBuffer.AddComponent<Insolvent>(indax, ello);    
    29.             }
    30.             else
    31.             {
    32.                 currentbuswages.MoneyHeld -= currentbuswages.Wages;
    33.             }
    34.         }
    35.     }
    36.  
    37.     [BurstCompile]
    38.     [RequireComponentTag(typeof(Person))]
    39.     struct ApplyWagesJob : IJobForEach<MoneyEntityInfo, PersonEntityInfo>
    40.     {
    41.         [NativeDisableParallelForRestriction][ReadOnly]
    42.         public ComponentDataFromEntity<Insolvent> busscheckunemploy;
    43.  
    44.         public void Execute(ref MoneyEntityInfo currentpeepswags, ref PersonEntityInfo workplace)
    45.         {
    46.             Entity anty = workplace.WorkPlaceEntityRef;
    47.             if (!busscheckunemploy.HasComponent(anty))
    48.             {
    49.                 currentpeepswags.MoneyHeld += currentpeepswags.Wages;
    50.              
    51.             }
    52.             else
    53.             {
    54.                 //Debug.Log("");
    55.             }
    56.  
    57.         }
    58.  
    59.     }    
    60.         protected override JobHandle OnUpdate(JobHandle inputDeps)
    61.     {
    62.      
    63.         var DeductWagesjooob = new DeductWagesJob()
    64.         {
    65.             //currentcomp = GetComponentDataFromEntity<MoneyEntityInfo>(false),
    66.             GlobalWages = World.GetExistingSystem<TempAssignMoneyValuesatStart>().GlobalWages,
    67.             commandsBuffer = m_EntityCommandBufferSystem.CreateCommandBuffer().ToConcurrent()
    68.         };//.Schedule(this, inputDeps);
    69.  
    70.         JobHandle deductjobshand = DeductWagesjooob.Schedule(this, inputDeps);
    71.  
    72.         deductjobshand.Complete();
    73.  
    74.         m_EntityCommandBufferSystem.AddJobHandleForProducer(deductjobshand);
    75.  
    76.         EntityCommandBufferSystem commbuffsyst;// new EntityCommandBufferSystem();
    77.  
    78.         var Applywagesjoob = new ApplyWagesJob()
    79.         {
    80.             busscheckunemploy = GetComponentDataFromEntity<Insolvent>(true)
    81.  
    82.         };
    83.  
    84.         JobHandle ApplywagsHandle = Applywagesjoob.Schedule(this, inputDeps);
    85.         inputDeps = ApplywagsHandle;    
    86.      
    87.         inputDeps.Complete();
    88.      
    89.         if(inputDeps.IsCompleted)
    90.         {
    91.          
    92.             this.Enabled = false;
    93.         }
    94.  
    95.         return inputDeps;//DeductWagesjooob.Schedule(this, inputDeps);
    96.  
    97.     }
    98.  
    99. }

    I just messed around and I think I figured out a way. I just called update() on the m_EntityCommandBufferSystem and that seems to work, not sure if it's the best way though. I'd be curious to see those other ways if you are able to give a short examples.
     
  9. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    1,560
    You can just create a new buffer system by inheriting from EntityCommandBufferSystem

    Code (CSharp):
    1. [ExecuteAlways]
    2. public class VisionEntityCommandBufferSystem : EntityCommandBufferSystem
    3. {
    4. }
    It's not recommended to do this a lot as they are sync points but there are cases where it's needed.
     
  10. calabi

    calabi

    Joined:
    Oct 29, 2009
    Posts:
    84
    Thank's for the reply, I'm not very au fait with inheritance, I though you could avoid it mostly in DOTS. I guess I would use that pretty much as I did before.