Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

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,554
    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!