Search Unity

InvalidOperationException: The previously scheduled job reads from the NativeArray

Discussion in 'Entity Component System' started by mr-gmg, Mar 3, 2020.

  1. mr-gmg

    mr-gmg

    Joined:
    Aug 31, 2015
    Posts:
    62
    Hey guys, in one of my job I need to read LocalToWorld matrix, but another job writes to this LocalToWorld component. And I receive this exception.

    InvalidOperationException: The previously scheduled job RaycastSystem:RaycastJob reads from the NativeArray RaycastJob.Data.localToWorldType. You are trying to schedule a new job TRSToLocalToWorldSystem:TRSToLocalToWorld, which writes to the same NativeArray (via TRSToLocalToWorld.Data.LocalToWorldType). To guarantee safety, you must include RaycastSystem:RaycastJob as a dependency of the newly scheduled job.

    This situation actually happens pretty often and I really want to know how should I resolve it.
    I understand that I may complete my job and everything will be fine, or I may add a dependency to my job, but in case with LocalToWorld, I have no idea how to get the completion handle. And I don't like both these solutions.

    What is the correct way to resolve it?
     
  2. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,761
    Show jobs/systems. Simply passing handles and proper queries should solve this (as that's the entire point.)
     
    mr-gmg likes this.
  3. mr-gmg

    mr-gmg

    Joined:
    Aug 31, 2015
    Posts:
    62
    I have a custom raycast system, which works with LocalToWorld component. So, when I schedule RaycastJob I receive InvalidOperationException from my first comment.
    Code (CSharp):
    1. using Unity.Burst;
    2. using Unity.Collections;
    3. using Unity.Entities;
    4. using Unity.Jobs;
    5. using Unity.Mathematics;
    6. using Unity.Transforms;
    7. using UnityEngine;
    8. using BoxCollider = SE.Core.Collisions.BoxCollider;
    9. using SphereCollider = SE.Core.Collisions.SphereCollider;
    10.  
    11. public struct IgnoreRaycast : IComponentData {}
    12.  
    13. public class RaycastSystem : JobComponentSystem  {
    14.     [BurstCompile]
    15.     private struct RaycastJob : IJobChunk {
    16.         [ReadOnly] public ArchetypeChunkEntityType entityType;
    17.         [ReadOnly] public ArchetypeChunkComponentType<LocalToWorld> localToWorldType;
    18.         [ReadOnly] public ArchetypeChunkComponentType<BoxCollider> boxColliderType;
    19.         [ReadOnly] public ArchetypeChunkComponentType<SphereCollider> sphereColliderType;
    20.  
    21.         public Ray ray;
    22.         public NativeArray<Entity> closestEntityResult;
    23.      
    24.         [DeallocateOnJobCompletion]
    25.         public NativeArray<float> closestDistanceResult;
    26.  
    27.         private static float3 TransformNormal(in float3 normal, in float4x4 matrix) {
    28.             return new float3(
    29.                 normal.x * matrix.c0.x + normal.y * matrix.c1.x + normal.z * matrix.c2.x,
    30.                 normal.x * matrix.c0.y + normal.y * matrix.c1.y + normal.z * matrix.c2.y,
    31.                 normal.x * matrix.c0.z + normal.y * matrix.c1.z + normal.z * matrix.c2.z);
    32.         }
    33.  
    34.         private bool hit_sphere(in float3 center, in float radius, in float3 ro, in float3 rd, out float distance) {
    35.             distance = float.MaxValue;
    36.             float3 oc = ro - center;
    37.             float a = math.dot(rd, rd);
    38.             float b = (float) 2.0 * math.dot(oc, rd);
    39.             float c = math.dot(oc, oc) - radius * radius;
    40.             float discriminant = b * b - 4 * a * c;
    41.             if (discriminant < 0.0) {
    42.                 return false;
    43.             } else {
    44.                 float numerator = -b - math.sqrt(discriminant);
    45.                 if (numerator > 0.0) {
    46.                     distance = (float) (numerator / (2.0 * a));
    47.                     return true;
    48.                 }
    49.  
    50.                 numerator = -b + math.sqrt(discriminant);
    51.                 if (numerator > 0.0) {
    52.                     distance = (float) (numerator / (2.0 * a));
    53.                     return true;
    54.                 } else {
    55.                     return false;
    56.                 }
    57.             }
    58.         }
    59.  
    60.         public void Execute(ArchetypeChunk chunk, int chunkIndex, int firstEntityIndex) {
    61.             if (chunk.Has(boxColliderType)) {
    62.                 var entities = chunk.GetNativeArray(entityType);
    63.                 var chunkLocalToWorlds = chunk.GetNativeArray(localToWorldType);
    64.                 var chunkBoxColliders = chunk.GetNativeArray(boxColliderType);
    65.  
    66.                 for (var i = 0; i < chunk.Count; i++) {
    67.                     float4x4 worldToLocalMatrix = math.inverse(chunkLocalToWorlds[i].Value);
    68.  
    69.                     Ray localRay = ray;
    70.                     localRay.origin = math.transform(worldToLocalMatrix, localRay.origin);
    71.                     localRay.direction = math.normalize(TransformNormal(localRay.direction, worldToLocalMatrix));
    72.                  
    73.                     Bounds bounds = new Bounds(chunkBoxColliders[i].center, chunkBoxColliders[i].size);
    74.                     if (bounds.IntersectRay(localRay, out float distance)) {
    75.                         if (distance < closestDistanceResult[0]) {
    76.                             closestDistanceResult[0] = distance;
    77.                             closestEntityResult[0] = entities[i];
    78.                         }
    79.                     }
    80.                 }
    81.             } else if (chunk.Has(sphereColliderType)) {
    82.                 var entities = chunk.GetNativeArray(entityType);
    83.                 var chunkLocalToWorlds = chunk.GetNativeArray(localToWorldType);
    84.                 var sphereColliders = chunk.GetNativeArray(sphereColliderType);
    85.                 for (var i = 0; i < chunk.Count; i++) {
    86.                     float4x4 worldToLocalMatrix = math.inverse(chunkLocalToWorlds[i].Value);
    87.                  
    88.                     Ray localRay = ray;
    89.                     localRay.origin = math.transform(worldToLocalMatrix, localRay.origin);
    90.                     localRay.direction = math.normalize(TransformNormal(localRay.direction, worldToLocalMatrix));
    91.  
    92.                     if (hit_sphere(sphereColliders[i].center, sphereColliders[i].radius, localRay.origin, localRay.direction, out float distance)) {
    93.                         if (distance < closestDistanceResult[0]) {
    94.                             closestDistanceResult[0] = distance;
    95.                             closestEntityResult[0] = entities[i];
    96.                         }
    97.                     }
    98.                 }
    99.             }
    100.         }
    101.     }
    102.  
    103.     private EntityQuery m_group;
    104.  
    105.     protected override void OnCreate() {
    106.         base.OnCreate();
    107.         Enabled = false;
    108.         m_group = GetEntityQuery(new EntityQueryDesc {
    109.             All = new[] {
    110.                 ComponentType.ReadOnly<LocalToWorld>(),
    111.             },
    112.             Any = new[] {
    113.                 ComponentType.ReadOnly<BoxCollider>(),
    114.                 ComponentType.ReadOnly<SphereCollider>(),
    115.             },
    116.             None = new[] {
    117.                 ComponentType.ReadOnly<IgnoreRaycast>(),
    118.             },
    119.             Options = EntityQueryOptions.FilterWriteGroup
    120.         });
    121.     }
    122.  
    123.     public JobHandle Raycast(Ray ray, JobHandle inputDeps, NativeArray<Entity> closestEntityResult) {
    124.         NativeArray<float> closestDistanceResult = new NativeArray<float>(1, Allocator.TempJob, NativeArrayOptions.UninitializedMemory) {[0] = float.MaxValue};
    125.         JobHandle raycastJobHandle = new RaycastJob {
    126.             entityType = GetArchetypeChunkEntityType(),
    127.             localToWorldType = GetArchetypeChunkComponentType<LocalToWorld>(true),
    128.             boxColliderType = GetArchetypeChunkComponentType<BoxCollider>(true),
    129.             sphereColliderType = GetArchetypeChunkComponentType<SphereCollider>(true),
    130.             closestEntityResult = closestEntityResult,
    131.             closestDistanceResult = closestDistanceResult,
    132.             ray = ray,
    133.         }.Schedule(m_group, inputDeps);
    134.         return raycastJobHandle;
    135.     }
    136.  
    137.     protected override JobHandle OnUpdate(JobHandle inputDeps) {
    138.         return inputDeps;
    139.     }
    140. }
    141.  
    SelectionSystem uses the RaycastSystem
    Code (CSharp):
    1. using Unity.Collections;
    2. using Unity.Collections.LowLevel.Unsafe;
    3. using Unity.Entities;
    4. using Unity.Jobs;
    5. using UnityEngine;
    6.  
    7. public struct Selected : IComponentData {
    8. }
    9.  
    10. [AlwaysUpdateSystem]
    11. public class SelectionSystem : JobComponentSystem {
    12.     private struct SelectJob : IJob {
    13. #pragma warning disable 649
    14.         [NativeSetThreadIndex] int threadId;
    15. #pragma warning restore 649
    16.         public EntityCommandBuffer.Concurrent entityCommandBuffer;
    17.      
    18.         [DeallocateOnJobCompletion]
    19.         public NativeArray<Entity> closestEntityResult;
    20.         public void Execute() {
    21.             if (closestEntityResult[0] != Entity.Null) {
    22.                 entityCommandBuffer.AddComponent(threadId, closestEntityResult[0], new Selected());
    23.             }
    24.         }
    25.     }
    26.  
    27.     private EndSimulationEntityCommandBufferSystem m_endSimulationEntityCommandBufferSystem;
    28.     private RaycastSystem m_raycastSystem;
    29.  
    30.     protected override void OnCreate() {
    31.         base.OnCreate();
    32.         m_endSimulationEntityCommandBufferSystem = World.GetOrCreateSystem<EndSimulationEntityCommandBufferSystem>();
    33.         m_raycastSystem = World.GetOrCreateSystem<RaycastSystem>();
    34.     }
    35.  
    36.     protected override JobHandle OnUpdate(JobHandle inputDeps) {
    37.         if (MouseInput.leftButtonWasPressed) {
    38.             EntityCommandBuffer.Concurrent removeSelectedJobCommandBuffer = m_endSimulationEntityCommandBufferSystem.CreateCommandBuffer().ToConcurrent();
    39.             EntityCommandBuffer.Concurrent selectJobCommandBuffer = m_endSimulationEntityCommandBufferSystem.CreateCommandBuffer().ToConcurrent();
    40.  
    41.             NativeArray<Entity> closestEntityResult = new NativeArray<Entity>(1, Allocator.TempJob, NativeArrayOptions.UninitializedMemory){[0] = Entity.Null};
    42.          
    43.             JobHandle removeSelectedComponentsHandle = Entities.ForEach((Entity entity, int entityInQueryIndex, in Selected selected) => { removeSelectedJobCommandBuffer.RemoveComponent<Selected>(entityInQueryIndex, entity); }).Schedule(inputDeps);
    44.  
    45.             Ray ray = CameraAccessor.camera.ScreenPointToRay(MouseInput.position);
    46.             JobHandle raycastJobHandle = m_raycastSystem.Raycast(ray, removeSelectedComponentsHandle, closestEntityResult);
    47.  
    48.             JobHandle selectJobHandle = new SelectJob {
    49.                 entityCommandBuffer = selectJobCommandBuffer,
    50.                 closestEntityResult = closestEntityResult,
    51.             }.Schedule(raycastJobHandle);
    52.          
    53. m_endSimulationEntityCommandBufferSystem.AddJobHandleForProducer(removeSelectedComponentsHandle);
    54. m_endSimulationEntityCommandBufferSystem.AddJobHandleForProducer(selectJobHandle);
    55.             return selectJobHandle;
    56.         }
    57.         return inputDeps;
    58.     }
    59. }
    Maybe it is not the shortest example, but the Idea that I use LocalToWorld, and don't know how to work with it properly without calling JobHandle.Complete()
     
  4. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,761
    Oh. You're completely bypass the job/safety system by using m_raycastSystem = World.GetOrCreateSystem<RaycastSystem>();

    You really shouldn't do this, but if you insist you are responsible for manually handling job dependencies.

    Pretty much the issue is your system SelectionSystem has no dependency on LocalToWorld so the handle being passed in isn't the correct one when the system is scheduled.
     
    mr-gmg likes this.
  5. mr-gmg

    mr-gmg

    Joined:
    Aug 31, 2015
    Posts:
    62
    yeah, but how should it be ideally? for me it absolutely unclear what should I do to be able to use safely LocalToWorld, or Translation or whatever in my jobs?
     
  6. eizenhorn

    eizenhorn

    Joined:
    Oct 17, 2016
    Posts:
    2,685
    Maybe extract your raycast work from system and use it like utility and schedule it where you need (you can wrap all boilerplate code inside utility method and pass system to it and collect all ACCT etc.inside for exclude manual work every time)
     
    mr-gmg likes this.
  7. mr-gmg

    mr-gmg

    Joined:
    Aug 31, 2015
    Posts:
    62
    Oh, now I understood, I was really completely wrong with using RaycastSystem. I've done as @eizenhorn said, and it works. Thank both of you a lot!

    The only thing that I don't really like is GetEntityQuery is a protected method, and I can't create a query inside of my RaycastUtils. So, I created it in SelectionSystem and it looks ugly :) Is it the only approach to create EntityQuery in my case?

    Here is what I have now
    Code (CSharp):
    1. using Unity.Burst;
    2. using Unity.Collections;
    3. using Unity.Entities;
    4. using Unity.Jobs;
    5. using Unity.Mathematics;
    6. using Unity.Transforms;
    7. using UnityEngine;
    8. using BoxCollider = SE.Core.Collisions.BoxCollider;
    9. using SphereCollider = SE.Core.Collisions.SphereCollider;
    10.  
    11. public struct IgnoreRaycast : IComponentData {}
    12.  
    13. public static class RaycastUtils  {
    14.     [BurstCompile]
    15.     private struct RaycastJob : IJobChunk {
    16.         [ReadOnly] public ArchetypeChunkEntityType entityType;
    17.         [ReadOnly] public ArchetypeChunkComponentType<LocalToWorld> localToWorldType;
    18.         [ReadOnly] public ArchetypeChunkComponentType<BoxCollider> boxColliderType;
    19.         [ReadOnly] public ArchetypeChunkComponentType<SphereCollider> sphereColliderType;
    20.  
    21.         public Ray ray;
    22.         public NativeArray<Entity> closestEntityResult;
    23.      
    24.         [DeallocateOnJobCompletion]
    25.         public NativeArray<float> closestDistanceResult;
    26.  
    27.         private static float3 TransformNormal(in float3 normal, in float4x4 matrix) {
    28.             return new float3(
    29.                 normal.x * matrix.c0.x + normal.y * matrix.c1.x + normal.z * matrix.c2.x,
    30.                 normal.x * matrix.c0.y + normal.y * matrix.c1.y + normal.z * matrix.c2.y,
    31.                 normal.x * matrix.c0.z + normal.y * matrix.c1.z + normal.z * matrix.c2.z);
    32.         }
    33.  
    34.         private bool hit_sphere(in float3 center, in float radius, in float3 ro, in float3 rd, out float distance) {
    35.             distance = float.MaxValue;
    36.             float3 oc = ro - center;
    37.             float a = math.dot(rd, rd);
    38.             float b = (float) 2.0 * math.dot(oc, rd);
    39.             float c = math.dot(oc, oc) - radius * radius;
    40.             float discriminant = b * b - 4 * a * c;
    41.             if (discriminant < 0.0) {
    42.                 return false;
    43.             } else {
    44.                 float numerator = -b - math.sqrt(discriminant);
    45.                 if (numerator > 0.0) {
    46.                     distance = (float) (numerator / (2.0 * a));
    47.                     return true;
    48.                 }
    49.  
    50.                 numerator = -b + math.sqrt(discriminant);
    51.                 if (numerator > 0.0) {
    52.                     distance = (float) (numerator / (2.0 * a));
    53.                     return true;
    54.                 } else {
    55.                     return false;
    56.                 }
    57.             }
    58.         }
    59.  
    60.         public void Execute(ArchetypeChunk chunk, int chunkIndex, int firstEntityIndex) {
    61.             if (chunk.Has(boxColliderType)) {
    62.                 var entities = chunk.GetNativeArray(entityType);
    63.                 var chunkLocalToWorlds = chunk.GetNativeArray(localToWorldType);
    64.                 var chunkBoxColliders = chunk.GetNativeArray(boxColliderType);
    65.  
    66.                 for (var i = 0; i < chunk.Count; i++) {
    67.                     float4x4 worldToLocalMatrix = math.inverse(chunkLocalToWorlds[i].Value);
    68.  
    69.                     Ray localRay = ray;
    70.                     localRay.origin = math.transform(worldToLocalMatrix, localRay.origin);
    71.                     localRay.direction = math.normalize(TransformNormal(localRay.direction, worldToLocalMatrix));
    72.                  
    73.                     Bounds bounds = new Bounds(chunkBoxColliders[i].center, chunkBoxColliders[i].size);
    74.                     if (bounds.IntersectRay(localRay, out float distance)) {
    75.                         if (distance < closestDistanceResult[0]) {
    76.                             closestDistanceResult[0] = distance;
    77.                             closestEntityResult[0] = entities[i];
    78.                         }
    79.                     }
    80.                 }
    81.             } else if (chunk.Has(sphereColliderType)) {
    82.                 var entities = chunk.GetNativeArray(entityType);
    83.                 var chunkLocalToWorlds = chunk.GetNativeArray(localToWorldType);
    84.                 var sphereColliders = chunk.GetNativeArray(sphereColliderType);
    85.                 for (var i = 0; i < chunk.Count; i++) {
    86.                     float4x4 worldToLocalMatrix = math.inverse(chunkLocalToWorlds[i].Value);
    87.                  
    88.                     Ray localRay = ray;
    89.                     localRay.origin = math.transform(worldToLocalMatrix, localRay.origin);
    90.                     localRay.direction = math.normalize(TransformNormal(localRay.direction, worldToLocalMatrix));
    91.  
    92.                     if (hit_sphere(sphereColliders[i].center, sphereColliders[i].radius, localRay.origin, localRay.direction, out float distance)) {
    93.                         if (distance < closestDistanceResult[0]) {
    94.                             closestDistanceResult[0] = distance;
    95.                             closestEntityResult[0] = entities[i];
    96.                         }
    97.                     }
    98.                 }
    99.             }
    100.         }
    101.     }
    102.  
    103.     public static JobHandle Raycast(ComponentSystemBase system, EntityQuery group, Ray ray, JobHandle inputDeps, NativeArray<Entity> closestEntityResult) {
    104.         NativeArray<float> closestDistanceResult = new NativeArray<float>(1, Allocator.TempJob, NativeArrayOptions.UninitializedMemory) {[0] = float.MaxValue};
    105.         JobHandle raycastJobHandle = new RaycastJob {
    106.             entityType = system.GetArchetypeChunkEntityType(),
    107.             localToWorldType = system.GetArchetypeChunkComponentType<LocalToWorld>(true),
    108.             boxColliderType = system.GetArchetypeChunkComponentType<BoxCollider>(true),
    109.             sphereColliderType = system.GetArchetypeChunkComponentType<SphereCollider>(true),
    110.             closestEntityResult = closestEntityResult,
    111.             closestDistanceResult = closestDistanceResult,
    112.             ray = ray,
    113.         }.Schedule(group, inputDeps);
    114.         return raycastJobHandle;
    115.     }
    116. }
    117.  
    And SelectionSystem
    Code (CSharp):
    1. using Unity.Collections;
    2. using Unity.Collections.LowLevel.Unsafe;
    3. using Unity.Entities;
    4. using Unity.Jobs;
    5. using Unity.Transforms;
    6. using UnityEngine;
    7. using BoxCollider = SE.Core.Collisions.BoxCollider;
    8. using SphereCollider = SE.Core.Collisions.SphereCollider;
    9.  
    10. public struct Selected : IComponentData {
    11. }
    12.  
    13. [AlwaysUpdateSystem]
    14. public class SelectionSystem : JobComponentSystem {
    15.     private struct SelectJob : IJob {
    16. #pragma warning disable 649
    17.         [NativeSetThreadIndex] int threadId;
    18. #pragma warning restore 649
    19.         public EntityCommandBuffer.Concurrent entityCommandBuffer;
    20.      
    21.         [DeallocateOnJobCompletion]
    22.         public NativeArray<Entity> closestEntityResult;
    23.         public void Execute() {
    24.             if (closestEntityResult[0] != Entity.Null) {
    25.                 entityCommandBuffer.AddComponent(threadId, closestEntityResult[0], new Selected());
    26.             }
    27.         }
    28.     }
    29.  
    30.     private EndSimulationEntityCommandBufferSystem m_endSimulationEntityCommandBufferSystem;
    31.     private EntityQuery m_group;
    32.  
    33.     protected override void OnCreate() {
    34.         base.OnCreate();
    35.         m_endSimulationEntityCommandBufferSystem = World.GetOrCreateSystem<EndSimulationEntityCommandBufferSystem>();
    36.         m_group = GetEntityQuery(new EntityQueryDesc {
    37.             All = new[] {
    38.                 ComponentType.ReadOnly<LocalToWorld>(),
    39.             },
    40.             Any = new[] {
    41.                 ComponentType.ReadOnly<BoxCollider>(),
    42.                 ComponentType.ReadOnly<SphereCollider>(),
    43.             },
    44.             None = new[] {
    45.                 ComponentType.ReadOnly<IgnoreRaycast>(),
    46.             },
    47.             Options = EntityQueryOptions.FilterWriteGroup
    48.         });
    49.     }
    50.  
    51.     protected override JobHandle OnUpdate(JobHandle inputDeps) {
    52.         if (MouseInput.leftButtonWasPressed) {
    53.             EntityCommandBuffer.Concurrent removeSelectedJobCommandBuffer = m_endSimulationEntityCommandBufferSystem.CreateCommandBuffer().ToConcurrent();
    54.             EntityCommandBuffer.Concurrent selectJobCommandBuffer = m_endSimulationEntityCommandBufferSystem.CreateCommandBuffer().ToConcurrent();
    55.  
    56.             NativeArray<Entity> closestEntityResult = new NativeArray<Entity>(1, Allocator.TempJob, NativeArrayOptions.UninitializedMemory){[0] = Entity.Null};
    57.          
    58.             JobHandle removeSelectedComponentsHandle = Entities.ForEach((Entity entity, int entityInQueryIndex, in Selected selected) => {
    59.                 removeSelectedJobCommandBuffer.RemoveComponent<Selected>(entityInQueryIndex, entity);
    60.             }).Schedule(inputDeps);
    61.  
    62.             Ray ray = CameraAccessor.camera.ScreenPointToRay(MouseInput.position);
    63.             JobHandle raycastJobHandle = RaycastUtils.Raycast(this, m_group, ray, removeSelectedComponentsHandle, closestEntityResult);
    64.  
    65.             JobHandle selectJobHandle = new SelectJob {
    66.                 entityCommandBuffer = selectJobCommandBuffer,
    67.                 closestEntityResult = closestEntityResult,
    68.             }.Schedule(raycastJobHandle);
    69.             m_endSimulationEntityCommandBufferSystem.AddJobHandleForProducer(removeSelectedComponentsHandle);
    70.             m_endSimulationEntityCommandBufferSystem.AddJobHandleForProducer(selectJobHandle);
    71.             return selectJobHandle;
    72.         }
    73.         return inputDeps;
    74.     }
    75. }
    Take a look at how weird creation EntityQuery in SelectionSystem looks.
     
  8. Sarkahn

    Sarkahn

    Joined:
    Jan 9, 2013
    Posts:
    440
    You can also get an entity query through an entity manager. You can acccess the default one globally via
    World.DefaultGameObjectInjectionWorld.EntityManager


    https://docs.unity3d.com/Packages/c...ml?q=CreateEntityQuery#creating-a-entityquery
     
    mr-gmg likes this.
  9. mr-gmg

    mr-gmg

    Joined:
    Aug 31, 2015
    Posts:
    62
  10. eizenhorn

    eizenhorn

    Joined:
    Oct 17, 2016
    Posts:
    2,685
    It's not like Get, it's Create :) This query will be outside ReaderWriter safety chain, because it miss adding dependencies like GetEntityQuery do.
    upload_2020-3-6_12-36-15.png
    Also does many unnecessery work and you should cache it by yourself and not create every time. If you inside system you should always use GetEntityQuery.
    Correct me if I'm wrong :)
     
    Sarkahn and mr-gmg like this.
  11. mr-gmg

    mr-gmg

    Joined:
    Aug 31, 2015
    Posts:
    62
    Probably you're right but it works without any problem for me. So, I just moved entity query to RaycastUtils
    Code (CSharp):
    1.  
    2. private static EntityQuery m_group;
    3. private static EntityQuery m_groupLazy {
    4.     get {
    5.         if (m_group == null) {
    6.             m_group = World.DefaultGameObjectInjectionWorld.EntityManager.CreateEntityQuery(new EntityQueryDesc {
    7.                 All = new[] {
    8.                     ComponentType.ReadOnly<LocalToWorld>(),
    9.                 },
    10.                 Any = new[] {
    11.                     ComponentType.ReadOnly<BoxCollider>(),
    12.                     ComponentType.ReadOnly<SphereCollider>(),
    13.                 },
    14.                 None = new[] {
    15.                     ComponentType.ReadOnly<IgnoreRaycast>(),
    16.                 },
    17.                 Options = EntityQueryOptions.FilterWriteGroup
    18.             });
    19.         }
    20.         return m_group;
    21.     }
    22. }
    23.  
    24. [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
    25. private static void Init() {
    26.     m_group = null;
    27. }
    28.