Search Unity

[SOLVED] Current proper way to get entity data within a ForEach

Discussion in 'Entity Component System' started by JamesWjRose, May 21, 2020.

  1. JamesWjRose

    JamesWjRose

    Joined:
    Apr 13, 2017
    Posts:
    687
    A few months back the process was to create a job struct, add necessary data and that gets passed to Execute in a JobComponentSystem. During an upgrade of Unity and other DOTS components I see that "IJobForEach_BCCCC" is depreciated and I am converting my code to the current pattern. Prior I used the "GetComponentDataFromEntity" to get the data of an entity that is not part of the ForEach...

    Now, when I attempt to run the following code I get told:
    RoadDetailsFromEntity is not declared [ReadOnly] in a IJobParallelFor job. The container does not support parallel writing. Please use a more suitable container type.

    Various attempts to set that to [ReadOnly] gave various errors. So before I go farther down this path, my real question is; What is the corrent manner to get an entity, that is not part of the Entities.ForEach, and READ it?

    Thanks kindly.

    Code (CSharp):
    1. public class ER3D_TrafficSystem : JobComponentSystem
    2. {
    3.     [ReadOnly]private NativeArray<Entity> roadEntities;
    4.     private NativeArray<Entity> connectionEntities;
    5.     //[ReadOnly]public ComponentDataFromEntity<RoadDetails> RoadDetailsFromEntity;
    6.  
    7.     protected override void OnStartRunning()
    8.     {
    9.         EntityQuery allRoadsQuery = GetEntityQuery(
    10.             typeof(ERRoadTag),
    11.             ComponentType.ReadOnly<RoadDetails>(),
    12.             ComponentType.ReadOnly<LanePoints>());
    13.  
    14.  
    15.         roadEntities = allRoadsQuery.ToEntityArray(Allocator.Persistent);
    16.  
    17.         EntityQuery allConnectionsQuery = GetEntityQuery(
    18.             typeof(ERConnectionTag),
    19.             ComponentType.ReadOnly<ConnectionDetails>(),
    20.             ComponentType.ReadOnly<LanePoints>());
    21.  
    22.         connectionEntities = allConnectionsQuery.ToEntityArray(Allocator.Persistent);
    23.     }
    24.  
    25.     [BurstCompile]
    26.     protected override JobHandle OnUpdate(JobHandle inputDeps)
    27.     {
    28.         float dt = Time.DeltaTime;
    29.         float reachedPositionDistance = 2.5f;
    30.         NativeArray<Entity> roads = roadEntities;
    31.         NativeArray<Entity> connections = connectionEntities;
    32.         ComponentDataFromEntity<RoadDetails> RoadDetailsFromEntity = GetComponentDataFromEntity<RoadDetails>(true);
    33.         //[ReadOnly]ComponentDataFromEntity<RoadDetails> RoadDetailsFromEntity = GetComponentDataFromEntity<RoadDetails>(true);
    34.         //var RoadDetailsFromEntity = GetComponentDataFromEntity<RoadDetails>();
    35.         //RoadDetailsFromEntity = GetComponentDataFromEntity<RoadDetails>(true);
    36.  
    37.         var jobHandle = Entities.WithAll<ERAutoTag>()
    38.             .ForEach((
    39.             DynamicBuffer<AutoLanePoints> autoLanePoints,
    40.             ref AutoDetails autoDetails,
    41.             ref AutoPosition autoPosition,
    42.             ref Translation translation,
    43.             ref Rotation rotation) =>
    44.             {
    45.                 var distance = math.distance(autoPosition.Destination, translation.Value);
    46.  
    47.                 if (distance <= reachedPositionDistance)
    48.                 {
    49.                     autoPosition.CurrentPositionIndex += 1;
    50.  
    51.                     if (autoPosition.CurrentPositionIndex >= autoLanePoints.Length)
    52.                     {
    53.                         //get the next set of points
    54.                         autoPosition.CurrentPositionIndex = 0;
    55.                         //autoLanePoints.Clear();
    56.  
    57.                         for (int i = 0; i < roads.Length; i++)
    58.                         {
    59.                             //This is where the exception occurs
    60.                             RoadDetails roadDetails = RoadDetailsFromEntity[roads[i]];
    61.                         }
    62.  
    63.  
    64.                     }
    65.  
    66.                     autoPosition.Destination = autoLanePoints[autoPosition.CurrentPositionIndex].value;
    67.                 }
    68.  
    69.                 float3 lookVector = autoPosition.Destination - translation.Value;
    70.                 if (!lookVector.Equals(float3.zero))
    71.                 {
    72.                     Quaternion rotationLookAt = Quaternion.LookRotation(lookVector);
    73.                     rotation.Value = rotationLookAt;
    74.                 }
    75.  
    76.                 float3 smoothedPosition = math.lerp(translation.Value, autoPosition.Destination, autoDetails.speed * dt);
    77.                 translation.Value = smoothedPosition;
    78.  
    79.             }).Schedule(inputDeps);
    80.  
    81.         return jobHandle;
    82.     }
    83. }
     
  2. BackgroundMover

    BackgroundMover

    Joined:
    May 9, 2015
    Posts:
    224
    I think with Entities.ForEach there's a clause (similar to WithAll<>()) called WithReadOnly(myThing)
     
  3. DreamingImLatios

    DreamingImLatios

    Joined:
    Jun 3, 2017
    Posts:
    4,271
    Use SystemBase instead of JobComponentSystem and then you can call SystemBase.GetComponent.
     
    JamesWjRose likes this.
  4. JamesWjRose

    JamesWjRose

    Joined:
    Apr 13, 2017
    Posts:
    687
    Perfect. That was perfect, and QUICK. You rule.

    ----------------------------
    For others, here is what I am doing; I have two queries, roads and connections. When a auto reached the end of it's current road it needs to select the next from available options (instead of predeterminded)

    The following only does part of that, the full code (previous version, but it works is here: https://github.com/Blissgig/Easy-Road-3D-ECS-Traffic I will update it once I have it working in the new pattern.)

    Here is how to run a that process and get data that is not part of the Entities.ForEach
    Code (CSharp):
    1. public class ER3D_TrafficSystem : SystemBase
    2. {
    3.     private NativeArray<Entity> roadEntities;
    4.     private NativeArray<Entity> connectionEntities;
    5.    
    6.     protected override void OnStartRunning()
    7.     {
    8.         EntityQuery allRoadsQuery = GetEntityQuery(
    9.             typeof(ERRoadTag),
    10.             ComponentType.ReadOnly<RoadDetails>(),
    11.             ComponentType.ReadOnly<LanePoints>());
    12.  
    13.  
    14.         roadEntities = allRoadsQuery.ToEntityArray(Allocator.Persistent);
    15.  
    16.         EntityQuery allConnectionsQuery = GetEntityQuery(
    17.             typeof(ERConnectionTag),
    18.             ComponentType.ReadOnly<ConnectionDetails>(),
    19.             ComponentType.ReadOnly<LanePoints>());
    20.  
    21.         connectionEntities = allConnectionsQuery.ToEntityArray(Allocator.Persistent);
    22.     }
    23.  
    24.     [BurstCompile]
    25.     protected override void OnUpdate()
    26.     {
    27.         float dt = Time.DeltaTime;
    28.         float reachedPositionDistance = 2.5f;
    29.         NativeArray<Entity> roads = roadEntities;
    30.         NativeArray<Entity> connections = connectionEntities;
    31.         ComponentDataFromEntity<RoadDetails> RoadDetailsFromEntity = GetComponentDataFromEntity<RoadDetails>(true);
    32.  
    33.         Entities.WithAll<ERAutoTag>()
    34.             .ForEach((
    35.             DynamicBuffer<AutoLanePoints> autoLanePoints,
    36.             ref AutoDetails autoDetails,
    37.             ref AutoPosition autoPosition,
    38.             ref Translation translation,
    39.             ref Rotation rotation) =>
    40.             {
    41.                 var distance = math.distance(autoPosition.Destination, translation.Value);
    42.  
    43.                 if (distance <= reachedPositionDistance)
    44.                 {
    45.                     autoPosition.CurrentPositionIndex += 1;
    46.  
    47.                     if (autoPosition.CurrentPositionIndex >= autoLanePoints.Length)
    48.                     {
    49.                         autoPosition.CurrentPositionIndex = 0;
    50.                         //autoLanePoints.Clear();
    51.  
    52.                         for (int i = 0; i < roads.Length; i++)
    53.                         {
    54.                             RoadDetails roadDetails = RoadDetailsFromEntity[roads[i]];
    55.  
    56.                             //TODO: More of the selection logic will go here.
    57.                         }
    58.                     }
    59.  
    60.                     autoPosition.Destination = autoLanePoints[autoPosition.CurrentPositionIndex].value;
    61.                 }
    62.  
    63.  
    64.                 float3 lookVector = autoPosition.Destination - translation.Value;
    65.                 if (!lookVector.Equals(float3.zero))
    66.                 {
    67.                     Quaternion rotationLookAt = Quaternion.LookRotation(lookVector);
    68.                     rotation.Value = rotationLookAt;
    69.                 }
    70.  
    71.                 float3 smoothedPosition = math.lerp(translation.Value, autoPosition.Destination, autoDetails.speed * dt);
    72.                 translation.Value = smoothedPosition;
    73.  
    74.             }).Schedule();
    75.     }