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.

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.