Search Unity

[Solved]Problem injecting ComponentDataFromEntity when intended to write in component data

Discussion in 'Data Oriented Technology Stack' started by Dan4x8, Oct 26, 2018.

  1. Dan4x8

    Dan4x8

    Joined:
    Feb 27, 2015
    Posts:
    6
    Hi all.
    I'm quiet new to the ECS and probably I just overlooked something very important.
    In some of my entities I need references to others to fetch some component values of them. This works quiet well with an Entity field and injecting the desired components into the job.
    In example like this (note: this is something that works):
    Code (CSharp):
    1.  
    2.     [Inject] private ComponentDataFromEntity<Position> _posData;
    3.  
    4.     [BurstCompile]
    5.     struct RotateToAttractorJob : IJobProcessComponentData<Position, Rotation, Attractor>
    6.     {
    7.         [ReadOnly] public ComponentDataFromEntity<Position> positions;
    8.  
    9.         public void Execute([ReadOnly] ref Position position, [WriteOnly] ref Rotation rotation, [ReadOnly] ref Attractor attractor)
    10.         {
    11.             //Do fancy stuff - NOT relevant to the problem
    12.         }
    13.     }
    14.     protected override JobHandle OnUpdate(JobHandle inputDeps)
    15.     {
    16.         RotateToAttractorJob rtaJob = new RotateToAttractorJob()
    17.         {
    18.             positions = _posData
    19.         };
    20.         JobHandle rtaHandle = rtaJob.Schedule(this, inputDeps);
    21.         return rtaHandle;
    22.     }
    But... something like this will not work and throw an exception
    Code (CSharp):
    1.  
    2.     [Inject] private ComponentDataFromEntity<Position> _posData;
    3.  
    4.     [BurstCompile]
    5.     struct RotateToAttractorJob : IJobProcessComponentData<Position, Rotation, Attractor>
    6.     {
    7.         [ReadOnly] public ComponentDataFromEntity<Position> positions;
    8.  
    9.         //Please note the absence of the [ReadOnly] Attribute on the position parameter
    10.         public void Execute(ref Position position, [WriteOnly] ref Rotation rotation, [ReadOnly] ref Attractor attractor)
    11.         {
    12.             //code here still doesnt matter
    13.         }
    14.     }
    15.     protected override JobHandle OnUpdate(JobHandle inputDeps)
    16.     {
    17.         RotateToAttractorJob rtaJob = new RotateToAttractorJob()
    18.         {
    19.             positions = _posData
    20.         };
    21.         JobHandle rtaHandle = rtaJob.Schedule(this, inputDeps);
    22.         return rtaHandle;
    23.     }
    So what should I do, if I want to edit 'my position' in relation to a referenced position (ie: chasing another entity)? What am I missing?
     
  2. eizenhorn

    eizenhorn

    Joined:
    Oct 17, 2016
    Posts:
    1,423
    And it's of course expected and correct behaviour, in second case you read and write in parallel in to same positions array in chunks, it's aliasing. If you absolutely shure than you not write and read in to same element in positions array you can use [NativeDisableParallelForRestriction] attribute on ComponentDataFromEntity.
     
  3. Dan4x8

    Dan4x8

    Joined:
    Feb 27, 2015
    Posts:
    6
    I already thought that it would be something in that direction, since it makes sense.
    Unfortunately the [NativeDisableParallelForRestriction] still doesn't work (even with an empty execute block). But thanks for the hint.
    Also, while I know what I do in each iteration of the Job I wouldn't be able guarantee that no read and write would try access the same position at the same time. Even the opposite I think...since I want entities chasing other entities based on various factors and they're all moving.

    I'll take another closer look at the pure twin stick example since basically the enemy missiles are chasing a moving player entity.

    Btw, I fooled around first with a very hybrid approach with a very very interesting result. I had a reference to a target gameobject in the wrapper and used update to overwrite the ComponentData (of course, tbis defeated the purpose of the ecs/jobs). Funny thing though, it seemed to work at first glance. Even funnier...only when I selected the target object in the hierarchy in the editor.

    But thanks anyway ^^'
     
  4. eizenhorn

    eizenhorn

    Joined:
    Oct 17, 2016
    Posts:
    1,423
    Just use IJobProcessComponentDataWitEntity and set Position and Rotation in RequireComponetTagAttribute (or not set, if is enough Attractor for handle required entities) and just put them as ComponentDataFromEntity
    Code (CSharp):
    1.  
    2. [RequireComponentTag(typeof(Position), typeof(Rotation))] //<-- not require if Attractor enough
    3. [BurstCompile]
    4.     struct RotateToAttractorJob : IJobProcessComponentDataWithEntity<Attractor>
    5.     {
    6.         [NativeDisableParallelForRestriction]  public ComponentDataFromEntity<Position> positions;
    7.         [NativeDisableParallelForRestriction]  public ComponentDataFromEntity<Rotation> rotations;
    8.         public void Execute(Entity e, int index, [ReadOnly] ref Attractor attractor)
    9.         {
    10.            
    11.         }
    12.     }
     
    Last edited: Oct 26, 2018
    Dan4x8 likes this.
  5. Dan4x8

    Dan4x8

    Joined:
    Feb 27, 2015
    Posts:
    6
    Thanks alot, This did the trick :)