Search Unity

Question Query and lookup to same component data in single job? Error: "two containers may not be the same"

Discussion in 'Entity Component System' started by Botaurus, Jan 26, 2023.

  1. Botaurus

    Botaurus

    Joined:
    Feb 20, 2013
    Posts:
    81
    I have a iComponentData called 'Boids'. My boids are casting to find other boids (the boids have data about how to interact with each other). So I have a query for a read/write Boid container and a readonly lookup so I can lookup the other boids found by a sphere cast. I get an error saying " two containers may not be the same (aliasing)."

    I can solve my problem by splitting boids into two separate components with redundant data, but I wanted to check if there's something I'm missing that makes this possible?

    Thank you

    Code (CSharp):
    1.  [BurstCompile]
    2.     [WithAll(typeof(SimBoidFollowerTag))]
    3.     public partial struct BoidSimulation : IJobEntity
    4.     {
    5.         [ReadOnly] public float2 LeaderPos;
    6.         [ReadOnly] public float2 LeaderVel;
    7.         [ReadOnly] public int CastGrp;
    8.         [ReadOnly] public CollisionWorld ColWorld;
    9.         [ReadOnly] public BoidConfigData configBoid;
    10.         [ReadOnly] public ComponentLookup<AgentMove2d> OtherAgentMoves;
    11.         [ReadOnly] public ComponentLookup<LoopableAgent> LoopableAgents;
    12.         [ReadOnly] public ComponentLookup<Boid> OtherBoids;
    13.  
    14.         [ReadOnly] public float DeltaTime;
    15.  
    16.         [BurstCompile]
    17.         void Execute(Entity entity, RefRW<Boid> boid, TransformAspect trans)
    18.         {
    19.             float2 cohesionAverage = float2.zero;
    20. ...
     
  2. Tony_Max

    Tony_Max

    Joined:
    Feb 7, 2017
    Posts:
    353
    You can break through safe system by adding
    [NativeDisableContainerSafetyRestriction]
    to your
    ComponentLookup
    field.
     
    lberte likes this.
  3. Botaurus

    Botaurus

    Joined:
    Feb 20, 2013
    Posts:
    81
    In this circumstance is it safe to do so? Should I avoid needing to use NativeDisableContainerSafetyRestriction?
    Thank you for the reply
     
  4. Tony_Max

    Tony_Max

    Joined:
    Feb 7, 2017
    Posts:
    353
    I guess yes, it should be safe. But it can depends on how you use lookup. Actually I wonder why there is restriction about using lookup and query component in same job.
     
    Botaurus likes this.
  5. MaNaRz

    MaNaRz

    Joined:
    Aug 24, 2017
    Posts:
    117
    Writing to EntityA and reading from EntityB at the same time with the same component is a race condition. EntityB could want to read from EntityA later on in the same job. Since the order is not guaranteed you end up with different results depending on wether EntityA or B did the write first.
    If you are sure that you are not reading and writing to the same entities then its okay to disable safety.
     
    Tony_Max and Botaurus like this.
  6. Arnold_2013

    Arnold_2013

    Joined:
    Nov 24, 2013
    Posts:
    286
    An alternative is to get a copy of all the boids data (in a native array or something) and use this as your lookup data. (Double buffering, i think is the term)

    Or another alternative is the use of an 'Entity command buffer' to apply the write change at a later stage so you don't need the 'RefRW<Boid>', you can make it readonly.

    In most cases NativeDisable will be fine, even if race conditions do give issues it will only mess up your data. Which might not be a big problem. If you know the Entity in the query is never looked up in the ComponentLookup it will be fine. It is (always) the most performant solution, since for the other two more work needs to be done before or after the Job.
     
    Botaurus likes this.