Search Unity

InvalidOperationException: The writable NativeArray FreeMovementJob.materialPoints is the same Nativ

Discussion in 'Entity Component System' started by Vladimir-Borodin, Jul 2, 2018.

  1. Vladimir-Borodin

    Vladimir-Borodin

    Joined:
    Jun 1, 2017
    Posts:
    15
    Hi, here is my code:'
    Code (CSharp):
    1. [UpdateAfter(typeof(OrbitalMovementSystem))]
    2.     public class FreeMovementSystem : JobComponentSystem {
    3.         public struct Group {
    4.             public ComponentDataArray<MaterialPoint> materialPoints;
    5.             public ComponentDataArray<OrbitalData> orbitalDatas;
    6.             public ComponentDataArray<FreeMovement> freeMovements;
    7.             public int Length;
    8.         }
    9.         [Inject] private Group group;
    10.  
    11.         public struct Planets {
    12.             public ComponentDataArray<MaterialPoint> materialPoints;
    13.             public SubtractiveComponent<FreeMovement> freeMovement;
    14.             public int Length;
    15.         }
    16.         [Inject] private Planets planets;
    17.  
    18.         private struct FreeMovementJob : IJobParallelFor {
    19.             public long currentTime;
    20.             public NativeArray<MaterialPoint> materialPoints;
    21.             public NativeArray<OrbitalData> orbitalDatas;
    22.             public NativeArray<FreeMovement> freeMovements;
    23.             [ReadOnly]
    24.             public NativeArray<MaterialPoint> planets;
    25.             public void Execute(int index) {
    26.                 MaterialPoint m = materialPoints[index];
    27.                 OrbitalData o = orbitalDatas[index];
    28.                 FreeMovement f = freeMovements[index];
    29.                 double timeStep = (double)(GameData.Instance.dateTime - f.lastCalculationTime) / 10000000;
    30.                 OrbitalHelper.NextTrajectoryFrame(ref m, ref f, planets, timeStep);
    31.                 materialPoints[index] = m;
    32.                 freeMovements[index] = f;
    33.                 orbitalDatas[index] = o;
    34.             }
    35.         }
    36.  
    37.         protected override JobHandle OnUpdate(JobHandle inputDeps) {
    38.             FreeMovementJob j = new FreeMovementJob() {
    39.                 currentTime = GameData.Instance.dateTime,
    40.                 materialPoints = group.materialPoints.GetChunkArray(0, group.Length),
    41.                 orbitalDatas = group.orbitalDatas.GetChunkArray(0, group.Length),
    42.                 freeMovements = group.freeMovements.GetChunkArray(0, group.Length),
    43.                 planets = planets.materialPoints.GetChunkArray(0, planets.Length)
    44.             };
    45.             return j.Schedule(group.Length, 10);
    46.         }
    47.     }
    At runtime I have InvalidOperationException:
    Seems two NativeArray<MaterialPoint> materialPoints; and NativeArray<MaterialPoint> planets; are not allowed to be in the same job.
    Why does it happen?
    Arrays are different, Group contains materialPoints from entities which also contain FreeMovement component, Planets contains SubtractiveComponent<FreeMovement>.
     
  2. dartriminis

    dartriminis

    Joined:
    Feb 3, 2017
    Posts:
    157
    Remember that there is only one array of MaterialPoint, no matter which entity it is attached to. So when you have two ComponentDataArray<MaterialPoint>, you are getting the same array, just a different iterator.

    You may need to separate this in to two jobs, and perform the trajectory calculations first (using temp job array for the results).
     
  3. Vladimir-Borodin

    Vladimir-Borodin

    Joined:
    Jun 1, 2017
    Posts:
    15
    I can't separate this, i need all planets to calculate values for each material point in Group.
    Obviously I can create different components for planets and other bodies (PlanetMaterialBody, VesselMaterialBody etc.), but this doesn't look like good solution.
     
  4. dartriminis

    dartriminis

    Joined:
    Feb 3, 2017
    Posts:
    157
    I didn't notice that was a parallel for job. Try adding [NativeDisableParallelForRestriction] to planets. Or try making it a regular IJob.
     
  5. 5argon

    5argon

    Joined:
    Jun 10, 2013
    Posts:
    1,555
    The solution is to put one `ComponentDataFromEntity<MaterialPoint>` instead of 2 `ComponentDataArray<MaterialPoint>` in the job you will get rid of aliasing problem. Then you differentiate between 2 set of injected MaterialPoint by adding additional `EntityArray` to the injection group. You use those entity as an indexer to CDFE. 2 `EntityArray` will not alias with each other.

    Also GetChunkArray is quite dangerous, you should just send the whole ComponentDataArray to the job since it was designed for that. (https://forum.unity.com/threads/sor...ent-isharedcomponentdata.534105/#post-3517414)
     
    Vladimir-Borodin likes this.
  6. Vladimir-Borodin

    Vladimir-Borodin

    Joined:
    Jun 1, 2017
    Posts:
    15
    Sadly, but both didn't help.

    P.S. Both dartriminis solutions.
     
  7. Vladimir-Borodin

    Vladimir-Borodin

    Joined:
    Jun 1, 2017
    Posts:
    15
    5argon, Looks a bit hacky, but it works. Thanks!