Search Unity

  1. Unity 2019.1 beta is now available.
    Dismiss Notice
  2. The Unity Pro & Visual Studio Professional Bundle gives you the tools you need to develop faster & collaborate more efficiently. Learn more.
    Dismiss Notice
  3. We're looking for insight from anyone who has experience with game testing to help us better Unity. Take our survey here. If chosen to participate you'll be entered into a sweepstake to win an Amazon gift card.
    Dismiss Notice
  4. On February 28th the Feedback website will shut down and be redirected to the Unity forums. See the full post for more information.
    Dismiss Notice
  5. Want to provide direct feedback to the Unity team? Join the Unity Advisory Panel.
    Dismiss Notice
  6. Unity 2018.3 is now released.
    Dismiss Notice
  7. Improve your Unity skills with a certified instructor in a private, interactive classroom. Watch the overview now.
    Dismiss Notice

How to fix dependency error when your system ?

Discussion in 'Entity Component System and C# Job system' started by Tazadar66, Oct 20, 2018.

  1. Tazadar66

    Tazadar66

    Joined:
    Aug 27, 2013
    Posts:
    54
    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:
    43
    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:
    54
    That's what I was looking for !

    Thanks for your help :)
     
  4. mitaywalle

    mitaywalle

    Joined:
    Jul 1, 2013
    Posts:
    67
    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:
    1,059
  6. mitaywalle

    mitaywalle

    Joined:
    Jul 1, 2013
    Posts:
    67
    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:
    1,059
    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.