Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Question Failing to schedule one job after the other one is completed

Discussion in 'Entity Component System' started by Liquid_Nalee, Apr 10, 2021.

  1. Liquid_Nalee

    Liquid_Nalee

    Joined:
    Mar 15, 2021
    Posts:
    19
    Hi,

    So basically I've tried using dependsOn to make one job be scheduled after my 1st job is completed.
    Here is the code:
    Code (CSharp):
    1. private void ResetSelection()
    2. {
    3.         var unselectJob = new SetSelectionJob
    4.         {
    5.             Hits = _selectionList,
    6.             Select = false,
    7.             ParallelWriter = _ecbSystem.CreateCommandBuffer().AsParallelWriter()
    8.         }
    9.         .Schedule(_selectionList.Length, 1);
    10.  
    11.         var clearSelectionJob = new ClearSelectionJob
    12.         {
    13.            Hits = _selectionList
    14.         }
    15.         .Schedule(unselectJob);
    16.            
    17.         _ecbSystem.AddJobHandleForProducer(clearSelectionJob);
    18. }
    19.  
    20. [BurstCompile]
    21. private struct SetSelectionJob: IJobParallelFor
    22. {
    23.     [ReadOnly] public NativeList<ColliderCastHit> Hits;
    24.     [ReadOnly] public bool Select;
    25.     [WriteOnly] public EntityCommandBuffer.ParallelWriter ParallelWriter;
    26.  
    27.     public void Execute(int index)
    28.     {
    29.         if (Select)
    30.             ParallelWriter.AddComponent<SelectedTag>(index, Hits[index].Entity);
    31.         else
    32.             ParallelWriter.RemoveComponent<SelectedTag>(index, Hits[index].Entity);
    33.     }
    34. }
    35.  
    36. [BurstCompile]
    37. private struct ClearSelectionJob : IJob
    38. {
    39.     [WriteOnly] public NativeList<ColliderCastHit> Hits;
    40.    
    41.     public void Execute()
    42.     {
    43.         Hits.Clear();
    44.     }
    45. }
    The idea is that I store selected items in a list, when I reset the selection, I need to clear the list.
    So what I try to do is start my job that sets the Selected stat and once that completed, I wanna clear the list, so I scheduling my job that clears the list and make it depend on the job that sets the selection.
    Then finally, I want it all to resolve at the EndFixedStepSimulationCommandBufferSystem so I add the job handle of the 2nd job to the ECB system.

    what actually happens is this:
    Code (CSharp):
    1. InvalidOperationException: The previously scheduled job SelectionSystem:SetSelectionJob reads from the Unity.Collections.NativeList`1[Unity.Physics.ColliderCastHit] SetSelectionJob.Hits. You must call JobHandle.Complete() on the job SelectionSystem:SetSelectionJob, before you can write to the Unity.Collections.NativeList`1[Unity.Physics.ColliderCastHit] safely.
    2. Unity.Collections.LowLevel.Unsafe.AtomicSafetyHandle.CheckWriteAndBumpSecondaryVersion (Unity.Collections.LowLevel.Unsafe.AtomicSafetyHandle handle) (at <9244fb8344e84288877b43b45b29c242>:0)
    I get an error saying the ClearSelectionJob is trying to write while the SetSelectionJob is still reading which shouldn't happen. Even if I add "unselectJob.Complete()" before I schedule the ClearSelectionJob I am still getting the error and that I absolutely do not get ?

    Thanks in advance for the help
     
  2. Liquid_Nalee

    Liquid_Nalee

    Joined:
    Mar 15, 2021
    Posts:
    19
    So I eventually figured it out actually.

    For those struggling like me, here is the fix.
    So actually the error is due to the entire system rerunning before the SetSelectionJob completed.
    To fix it, instead of adding just SetSelectionJob to the ECB System as a producer, you need to add the system's dependency like so:
    Code (CSharp):
    1. private void ResetSelection()
    2. {
    3.     var unselectJob = new SetSelectionJob
    4.                       {
    5.                           Hits = _selectionList,
    6.                           Select = false,
    7.                           ParallelWriter = _ecbSystem.CreateCommandBuffer()
    8.                                                      .AsParallelWriter()
    9.                       }.Schedule(_selectionList.Length, 1);
    10.  
    11.     var clearSelectionJob =
    12.         new ClearSelectionJob {Hits = _selectionList}.Schedule(unselectJob);
    13.  
    14.     _ecbSystem.AddJobHandleForProducer(
    15.         JobHandle.CombineDependencies(Dependency, unselectJob, clearSelectionJob)
    16.     );
    17. }