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

How to fix dependency error when your system ?

Discussion in 'Entity Component System' started by Tazadar66, Oct 20, 2018.

  1. Tazadar66

    Tazadar66

    Joined:
    Aug 27, 2013
    Posts:
    57
    Hello there I have this error and I don't know how I can fix this...

    InvalidOperationException: The previously scheduled job CopyTransformFromGameObjectSystem:CopyTransforms writes to the NativeArray CopyTransforms.positions. You are trying to schedule a new job AddUpdatedUnitsInSubgridSystem:MyJob, which reads from the same NativeArray (via MyJob.positions). To guarantee safety, you must include CopyTransformFromGameObjectSystem:CopyTransforms as a dependency of the newly scheduled job.

    Here is my code and I don't really know why it is not working :(

    Code (CSharp):
    1. using Unity.Entities;
    2. using Unity.Collections;
    3. using Unity.Jobs;
    4. using Unity.Transforms;
    5. using Unity.Burst;
    6.  
    7. [UpdateAfter(typeof(CopyTransformFromGameObjectSystem))]
    8. public class AddUpdatedUnitsInSubgridSystem : JobComponentSystem
    9. {
    10.     public struct GridData
    11.     {
    12.         public readonly int Length;
    13.         public BufferArray<SubGridUnitComponent> subgridUnits;
    14.         public BufferArray<SubGridNeighborComponent> subgridNeighbors;
    15.         public ComponentDataArray<SubGridComponent> subgridComponents;
    16.     }
    17.  
    18.     [Inject] GridData m_gridData;
    19.  
    20.     [BurstCompile]
    21.     public struct MyJob : IJobParallelFor
    22.     {
    23.         [ReadOnly]
    24.         public ComponentDataFromEntity<Position> positions;
    25.         [ReadOnly]
    26.         public BufferFromEntity<SubGridUnitComponent> subGridUnitBuffers;
    27.  
    28.         [ReadOnly]
    29.         public BufferArray<SubGridNeighborComponent> subgridNeighbors;
    30.         [ReadOnly]
    31.         public ComponentDataArray<SubGridComponent> subgridComponents;
    32.  
    33.         public BufferArray<SubGridUnitComponent> subgridUnits;
    34.  
    35.         public void Execute(int j)
    36.         {
    37.             for(int i = 0; i < subgridNeighbors[j].Length; ++i)
    38.             {
    39.                 int size = subGridUnitBuffers[subgridNeighbors[j][i].neighborEntity].Length;
    40.                 for(int k = 0; k < size; ++k)
    41.                 {
    42.                     Entity e = subGridUnitBuffers[subgridNeighbors[j][i].neighborEntity][k].entity;
    43.                     Position pos = positions[e];
    44.  
    45.                     if(pos.Value.y >= subgridComponents[j].bottomLeft.y &&
    46.                     pos.Value.y < subgridComponents[j].topRight.y &&
    47.                     pos.Value.x >= subgridComponents[j].bottomLeft.x &&
    48.                     pos.Value.x < subgridComponents[j].topRight.x)
    49.                     {
    50.                         subgridUnits[j].Add(new SubGridUnitComponent(e));
    51.                     }
    52.                 }
    53.             }
    54.         }
    55.     }
    56.  
    57.     protected override JobHandle OnUpdate(JobHandle inputDeps)
    58.     {
    59.         // Get all we need first
    60.         EntityManager entityManager = World.Active.GetExistingManager<EntityManager>();
    61.         ComponentDataFromEntity<Position> unitPositions = entityManager.GetComponentDataFromEntity<Position>(true);
    62.         BufferFromEntity<SubGridUnitComponent> subGridUnitBuffers = entityManager.GetBufferFromEntity<SubGridUnitComponent>(true);
    63.        
    64.         // Compute stuff here
    65.         MyJob job = new MyJob()
    66.         {
    67.             positions = unitPositions,
    68.             subGridUnitBuffers = subGridUnitBuffers,
    69.             subgridComponents = m_gridData.subgridComponents,
    70.             subgridNeighbors = m_gridData.subgridNeighbors,
    71.             subgridUnits = m_gridData.subgridUnits
    72.         };
    73.         return job.Schedule(m_gridData.Length, 64, inputDeps);
    74.     }
    75. }

    Thank you :)
     
  2. DreamingImLatios

    DreamingImLatios

    Joined:
    Jun 3, 2017
    Posts:
    4,223
    Don't use EntityManager.GetComponentDataFromEntity. Use JobComponentSystem.GetComponentDataFromEntity. That version sets up R/W dependencies and then calls the EntityManager version. I ran into the same issue with Chunk Iteration a few weeks ago. As a rule always use the ComponentSystem methods over EntityManager methods if they have them. It is a bit confusing.

    Also, you don't need to fetch EntityManager. JobComponentSystem has an auto-assigned property named EntityManager that uses the world the system is part of.
     
    Tazadar66 likes this.
  3. Tazadar66

    Tazadar66

    Joined:
    Aug 27, 2013
    Posts:
    57
    That's what I was looking for !

    Thanks for your help :)
     
  4. mitaywalle

    mitaywalle

    Joined:
    Jul 1, 2013
    Posts:
    247
    Hi guys!
    Have similar error and don't undestand how can I get data from this native array

    Here's code
    Code (CSharp):
    1. [BurstCompile,UpdateAfter(typeof(CopyTransformFromGameObjectSystem))]
    2.     public sealed class SA_manager : JobComponentSystem
    3.     {
    4.         public struct Components
    5.         {
    6.             public EntityArray Entities;
    7.             public ComponentDataArray<SA_data> source;
    8.             public readonly ComponentDataArray<Position> p;
    9.  
    10.             public readonly int Length;
    11.         }
    12.  
    13.         [Inject] Components data;
    14.  
    15.         protected override JobHandle OnUpdate(JobHandle inputDeps)
    16.         {
    17.             var listeners = GetComponentGroup(typeof(SA_ListenerData), typeof(Position)).GetComponentDataArray<Position>();
    18.          
    19.             SA_ProcessingJob job = new SA_ProcessingJob
    20.             {
    21.                 listenerPos = listeners.Length == 0 ? float3(0f,0f,0f): listeners[0].Value
    22.             };
    23.          
    24.             return job.Schedule(this, inputDeps);
    25.         }
    26.  
    27.         [BurstCompile]
    28.         struct SA_ProcessingJob : IJobProcessComponentData<SA_data, Position>
    29.         {
    30.             internal float3 listenerPos;
    31.          
    32.             public void Execute(ref SA_data source, [ReadOnly]ref Position p)
    33.             {
    34.                 // processing
    35.             }
    36.         }
    37.     }
     
  5. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,753
  6. mitaywalle

    mitaywalle

    Joined:
    Jul 1, 2013
    Posts:
    247
    Hi, thanks for advise, but best practices also tolds to use IJobProcessComponentData for many entities. Why should I choose more complicated chunk iteration?

    May be in this case more important to use GetComponentGroup instead of [Inject] ComponentDataArray ?

    Or May be I missunderstood something in your answer...
     
  7. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,753
    Yes you should use IJobProcessComponentData, but if you're iterating 2 separate queries you need to use chunk iterations on at least the secondary SA_ListenerData group.

    Anyway your actual issue is this listeners[0] is not safe without completing your job dependencies which don't happen automatically in a JobComponentGroup.