Search Unity

  1. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice
  2. Unity is excited to announce that we will be collaborating with TheXPlace for a summer game jam from June 13 - June 19. Learn more.
    Dismiss Notice
  3. Dismiss Notice

Question Getting Error Attempting CollisionWorld.CastRay

Discussion in 'Physics for ECS' started by JamesPardue, May 23, 2021.

  1. JamesPardue

    JamesPardue

    Joined:
    Mar 6, 2020
    Posts:
    6
    So I'm trying to do a simple parallel scan.

    Script that does the scan:
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using Unity.Entities;
    4. using Unity.Transforms;
    5. using Unity.Physics;
    6. using Unity.Physics.Systems;
    7. using Unity.Mathematics;
    8. using Unity.Collections;
    9. using Unity.Jobs;
    10. using UnityEngine;
    11.  
    12. public class RayScanner : MonoBehaviour
    13. {
    14.     // Start is called before the first frame update
    15.     void Start(){}
    16.  
    17.     public void TDRaycast(CollisionWorld collisionWorld)//, NativeList<Unity.Physics.RaycastHit> allHits)
    18.     {
    19.         float3 RayFrom = new float3(1f, 1f, 1f);
    20.         float3 RayTo = new float3(1f, -1f, 1f);
    21.  
    22.         RaycastInput input = new RaycastInput()
    23.         {
    24.             Start = RayFrom,
    25.             End = RayTo,
    26.             Filter = new CollisionFilter()
    27.             {
    28.                 BelongsTo = ~0u,
    29.                 CollidesWith = ~0u, // all 1s, so all layers, collide with everything
    30.                 GroupIndex = 0
    31.             }
    32.         };
    33.  
    34.         NativeList<Unity.Physics.RaycastHit> allHits = new NativeList<Unity.Physics.RaycastHit>();
    35.         collisionWorld.CastRay(input, ref allHits);
    36.     }
    37. }

    Script that creates the job:
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using Unity.Entities;
    4. using Unity.Transforms;
    5. using Unity.Physics;
    6. using Unity.Physics.Systems;
    7. using Unity.Mathematics;
    8. using Unity.Collections;
    9. using Unity.Jobs;
    10. using UnityEngine;
    11.  
    12. public class TriangleScanner : MonoBehaviour
    13. {
    14.     static RayScanner rayCaster;
    15.  
    16.     // Start is called before the first frame update
    17.     void Start()
    18.     {
    19.         rayCaster = new RayScanner();
    20.     }
    21.  
    22.     // Update is called once per frame
    23.     void Update()
    24.     {
    25.         TriScan();
    26.     }
    27.  
    28.     public struct RayCastJob : IJobParallelFor
    29.     {
    30.         public float3 from;
    31.         public float3 to;
    32.         //[ReadOnly] public CollisionWorld collisionWorld;
    33.         public CollisionWorld collisionWorld;
    34.  
    35.         public void Execute(int index)
    36.         {
    37.             rayCaster.TDRaycast(collisionWorld);
    38.         }
    39.     }
    40.  
    41.     public void TriScan()
    42.     {
    43.         var physicsWorldSystem = World.DefaultGameObjectInjectionWorld.GetExistingSystem<Unity.Physics.Systems.BuildPhysicsWorld>();
    44.         var collisionWorld = physicsWorldSystem.PhysicsWorld.CollisionWorld;
    45.  
    46.         RayCastJob job = new RayCastJob();
    47.         job.collisionWorld = collisionWorld;
    48.         JobHandle handle = job.Schedule(2, 1);
    49.  
    50.         handle.Complete();
    51.     }
    52. }
    53.  
    I get this error:
    Code (csharp):
    1.  
    2. InvalidOperationException: The native container has been declared as [ReadOnly] in the job, but you are writing to it.
    3. ...
    4. Unity.Physics.CollisionWorld.CastRay (Unity.Physics.RaycastInput input, Unity.Collections.NativeList`1[Unity.Physics.RaycastHit]& allHits) (at Library/PackageCache/com.unity.physics@0.4.1-preview/Unity.Physics/Collision/World/CollisionWorld.cs:196)
    5. RayScanner.TDRaycast (Unity.Physics.CollisionWorld collisionWorld) (at Assets/03_Mapping/TriDotScannng/RayScanner.cs:51)
    6. TriangleScanner+RayCastJob.Execute (System.Int32 index) (at Assets/03_Mapping/TriDotScannng/TriangleScanner.cs:37)
    7. Unity.Jobs.IJobParallelForExtensions+ParallelForJobStruct`1[T].Execute (T& jobData, System.IntPtr additionalPtr, System.IntPtr bufferRangePatchData, Unity.Jobs.LowLevel.Unsafe.JobRanges& ranges, System.Int32 jobIndex) (at <a1ac446df41c4a67becf2f8317dc1792>:0)
    8.  
    Is CastRay actually writing to the CollisionWorld? I thought it was only supposed to write to the 'Ref NativeList'.

    If I remove the [Read Only] from the CollisionWorld, I get this:
    Code (CSharp):
    1. IndexOutOfRangeException: Index 0 is out of restricted IJobParallelFor range [1...1] in ReadWriteBuffer.
    2. ReadWriteBuffers are restricted to only read & write the element at the job index. You can use double buffering strategies to avoid race conditions due to reading & writing in parallel to the same elements from a job.
    3. ...
    4. Unity.Physics.CollisionWorld.CastRay (Unity.Physics.RaycastInput input, Unity.Collections.NativeList`1[Unity.Physics.RaycastHit]& allHits) (at Library/PackageCache/com.unity.physics@0.4.1-preview/Unity.Physics/Collision/World/CollisionWorld.cs:196)
    5. RayScanner.TDRaycast (Unity.Physics.CollisionWorld collisionWorld) (at Assets/03_Mapping/TriDotScannng/RayScanner.cs:51)
    6. TriangleScanner+RayCastJob.Execute (System.Int32 index) (at Assets/03_Mapping/TriDotScannng/TriangleScanner.cs:37)
    7. Unity.Jobs.IJobParallelForExtensions+ParallelForJobStruct`1[T].Execute (T& jobData, System.IntPtr additionalPtr, System.IntPtr bufferRangePatchData, Unity.Jobs.LowLevel.Unsafe.JobRanges& ranges, System.Int32 jobIndex) (at <a1ac446df41c4a67becf2f8317dc1792>:0)
    And this:
    Code (CSharp):
    1. InvalidOperationException: The native container has been declared as [ReadOnly] in the job, but you are writing to it.
    2. Unity.Collections.LowLevel.Unsafe.AtomicSafetyHandle.CheckWriteAndBumpSecondaryVersion
    3. ...
    4. RayScanner.TDRaycast (Unity.Physics.CollisionWorld collisionWorld) (at Assets/03_Mapping/TriDotScannng/RayScanner.cs:51)
    5. TriangleScanner+RayCastJob.Execute (System.Int32 index) (at Assets/03_Mapping/TriDotScannng/TriangleScanner.cs:37)
    6. Unity.Jobs.IJobParallelForExtensions+ParallelForJobStruct`1[T].Execute (T& jobData, System.IntPtr additionalPtr, System.IntPtr bufferRangePatchData, Unity.Jobs.LowLevel.Unsafe.JobRanges& ranges, System.Int32 jobIndex) (at <a1ac446df41c4a67becf2f8317dc1792>:0)
    7. Unity.Jobs.JobHandle:ScheduleBatchedJobsAndComplete(JobHandle&)
    8. Unity.Jobs.JobHandle:Complete()
    9. TriangleScanner:TriScan() (at Assets/03_Mapping/TriDotScannng/TriangleScanner.cs:50)
    10. TriangleScanner:Update() (at Assets/03_Mapping/TriDotScannng/TriangleScanner.cs:25)
    Really not sure what I'm supposed to make of this, as I don't think I'm doing anything too complicated. Any help would be appreciated. Thanks.
     
  2. petarmHavok

    petarmHavok

    Joined:
    Nov 20, 2018
    Posts:
    461
    You need to declare CollisionWorld as [ReadOnly] in your job. That said, you have a bigger problem in this example - you are scheduling a job at a random point in time from the ECS point of view (during a GO update loop). That means you have to be sure all the relevant systems are finished, but also your job is finished before all the relevant systems start. I suggest looking at query samples and creating a system that schedules this job, otherwise you'll get into a lot of synchronization code that you will hardly ever get out of.