InvalidOperationException when performing raycast inside a job

I’m trying to perform raycasts inside a job. I have this code inside OnUpdate in a class derived from SystemBase:

var cmdBuffer = ecbSystem.CreateCommandBuffer().ToConcurrent();
CollisionWorld collisionWorld = buildPhysicsWorld.PhysicsWorld.CollisionWorld;

Entities
    .WithReadOnly(collisionWorld)
    .ForEach((Entity entity, int entityInQueryIndex, in DeployTroop deployTroop) =>
    {
        if (collisionWorld.CastRay(deployTroop.Raycast, out RaycastHit result))
        {
        }

        cmdBuffer.DestroyEntity(entityInQueryIndex, entity);
    })
    .Schedule();

ecbSystem.AddJobHandleForProducer(Dependency);

With this code I get 4 errors:
Error 1

InvalidOperationException: The previously scheduled job DeploymentSystem:<>c__DisplayClass_OnUpdate_LambdaJob0 reads from the Unity.Collections.NativeArray1[Unity.Physics.CollisionFilter] <>c__DisplayClass_OnUpdate_LambdaJob0.JobData.collisionWorld.Broadphase.m_StaticTree.BodyFilters. You are trying to schedule a new job Broadphase:PrepareStaticBodyDataJob, which writes to the same Unity.Collections.NativeArray1[Unity.Physics.CollisionFilter] (via PrepareStaticBodyDataJob.FiltersOut). To guarantee safety, you must include Deployme
Unity.Jobs.LowLevel.Unsafe.JobsUtility.ScheduleParallelForDeferArraySize (Unity.Jobs.LowLevel.Unsafe.JobsUtility+JobScheduleParameters& parameters, System.Int32 innerloopBatchCount, System.Void* listData, System.Void* listDataAtomicSafetyHandle) (at :0)
Unity.Jobs.IJobParallelForDeferExtensions.Schedule[T] (T jobData, System.Int32* forEachCount, System.Int32 innerloopBatchCount, Unity.Jobs.JobHandle dependsOn) (at Library/PackageCache/com.unity.jobs@0.2.7-preview.11/Unity.Jobs/IJobParallelForDefer.cs:111)
Unity.Jobs.IJobParallelForDeferExtensionsPhysics.ScheduleUnsafeIndex0[T] (T jobData, Unity.Collections.NativeArray1[T] forEachCount, System.Int32 innerloopBatchCount, Unity.Jobs.JobHandle dependsOn) (at Library/PackageCache/com.unity.physics@0.3.1-preview/Unity.Physics/Base/Jobs/IJobParallelForDeferExtensionsPhysics.cs:11) Unity.Physics.Broadphase.ScheduleStaticTreeBuildJobs (Unity.Physics.PhysicsWorld& world, System.Int32 numThreadsHint, Unity.Collections.NativeArray1[T] shouldDoWork, Unity.Jobs.JobHandle inputDeps) (at Library/PackageCache/com.unity.physics@0.3.1-preview/Unity.Physics/Collision/World/Broadphase.cs:186)
Unity.Physics.Broadphase.ScheduleBuildJobs (Unity.Physics.PhysicsWorld& world, System.Single timeStep, Unity.Mathematics.float3 gravity, Unity.Collections.NativeArray1[T] buildStaticTree, Unity.Jobs.JobHandle inputDeps, System.Int32 threadCountHint) (at Library/PackageCache/com.unity.physics@0.3.1-preview/Unity.Physics/Collision/World/Broadphase.cs:157) Unity.Physics.CollisionWorld.ScheduleBuildBroadphaseJobs (Unity.Physics.PhysicsWorld& world, System.Single timeStep, Unity.Mathematics.float3 gravity, Unity.Collections.NativeArray1[T] buildStaticTree, Unity.Jobs.JobHandle inputDeps, System.Int32 threadCountHint) (at Library/PackageCache/com.unity.physics@0.3.1-preview/Unity.Physics/Collision/World/CollisionWorld.cs:82)
Unity.Physics.Systems.BuildPhysicsWorld.OnUpdate (Unity.Jobs.JobHandle inputDeps) (at Library/PackageCache/com.unity.physics@0.3.1-preview/Unity.Physics/ECS/Systems/BuildPhysicsWorld.cs:241)
Unity.Entities.JobComponentSystem.Update () (at Library/PackageCache/com.unity.entities@0.8.0-preview.8/Unity.Entities/JobComponentSystem.cs:129)
Unity.Entities.ComponentSystemGroup.UpdateAllSystems () (at Library/PackageCache/com.unity.entities@0.8.0-preview.8/Unity.Entities/ComponentSystemGroup.cs:134)
UnityEngine.Debug:LogException(Exception)
Unity.Debug:LogException(Exception) (at Library/PackageCache/com.unity.entities@0.8.0-preview.8/Unity.Entities/Stubs/Unity/Debug.cs:19)
Unity.Entities.ComponentSystemGroup:UpdateAllSystems() (at Library/PackageCache/com.unity.entities@0.8.0-preview.8/Unity.Entities/ComponentSystemGroup.cs:138)
Unity.Entities.ComponentSystemGroup:OnUpdate() (at Library/PackageCache/com.unity.entities@0.8.0-preview.8/Unity.Entities/ComponentSystemGroup.cs:114)
Unity.Entities.ComponentSystem:Update() (at Library/PackageCache/com.unity.entities@0.8.0-preview.8/Unity.Entities/ComponentSystem.cs:108)
Unity.Entities.DummyDelegateWrapper:TriggerUpdate() (at Library/PackageCache/com.unity.entities@0.8.0-preview.8/Unity.Entities/ScriptBehaviourUpdateOrder.cs:152)

Error 2

InvalidOperationException: The previously scheduled job Jobs:CheckStaticBodyChangesJob reads from the UNKNOWN_OBJECT_TYPE CheckStaticBodyChangesJob.JobData.PositionType. You are trying to schedule a new job ExportPhysicsWorld:ExportDynamicBodiesJob, which writes to the same UNKNOWN_OBJECT_TYPE (via ExportDynamicBodiesJob.JobData.PositionType). To guarantee safety, you must include Jobs:CheckStaticBodyChangesJob as a dependency of the newly scheduled job.
Unity.Entities.JobChunkExtensions.ScheduleInternal[T] (T& jobData, Unity.Entities.EntityQuery query, Unity.Jobs.JobHandle dependsOn, Unity.Jobs.LowLevel.Unsafe.ScheduleMode mode, System.Boolean isParallel) (at Library/PackageCache/com.unity.entities@0.8.0-preview.8/Unity.Entities/IJobChunk.cs:212)
Unity.Entities.JobChunkExtensions.Schedule[T] (T jobData, Unity.Entities.EntityQuery query, Unity.Jobs.JobHandle dependsOn) (at Library/PackageCache/com.unity.entities@0.8.0-preview.8/Unity.Entities/IJobChunk.cs:93)
Unity.Physics.Systems.ExportPhysicsWorld.OnUpdate (Unity.Jobs.JobHandle inputDeps) (at Library/PackageCache/com.unity.physics@0.3.1-preview/Unity.Physics/ECS/Systems/ExportPhysicsWorld.cs:36)
Unity.Entities.JobComponentSystem.Update () (at Library/PackageCache/com.unity.entities@0.8.0-preview.8/Unity.Entities/JobComponentSystem.cs:129)
Unity.Entities.ComponentSystemGroup.UpdateAllSystems () (at Library/PackageCache/com.unity.entities@0.8.0-preview.8/Unity.Entities/ComponentSystemGroup.cs:134)
UnityEngine.Debug:LogException(Exception)
Unity.Debug:LogException(Exception) (at Library/PackageCache/com.unity.entities@0.8.0-preview.8/Unity.Entities/Stubs/Unity/Debug.cs:19)
Unity.Entities.ComponentSystemGroup:UpdateAllSystems() (at Library/PackageCache/com.unity.entities@0.8.0-preview.8/Unity.Entities/ComponentSystemGroup.cs:138)
Unity.Entities.ComponentSystemGroup:OnUpdate() (at Library/PackageCache/com.unity.entities@0.8.0-preview.8/Unity.Entities/ComponentSystemGroup.cs:114)
Unity.Entities.ComponentSystem:Update() (at Library/PackageCache/com.unity.entities@0.8.0-preview.8/Unity.Entities/ComponentSystem.cs:108)
Unity.Entities.DummyDelegateWrapper:TriggerUpdate() (at Library/PackageCache/com.unity.entities@0.8.0-preview.8/Unity.Entities/ScriptBehaviourUpdateOrder.cs:152)

Error 3

InvalidOperationException: The previously scheduled job Jobs:CheckStaticBodyChangesJob reads from the UNKNOWN_OBJECT_TYPE CheckStaticBodyChangesJob.JobData.LocalToWorldType. You are trying to schedule a new job TRSToLocalToWorldSystem:TRSToLocalToWorld, which writes to the same UNKNOWN_OBJECT_TYPE (via TRSToLocalToWorld.JobData.LocalToWorldType). To guarantee safety, you must include Jobs:CheckStaticBodyChangesJob as a dependency of the newly scheduled job.
Unity.Entities.JobChunkExtensions.ScheduleInternal[T] (T& jobData, Unity.Entities.EntityQuery query, Unity.Jobs.JobHandle dependsOn, Unity.Jobs.LowLevel.Unsafe.ScheduleMode mode, System.Boolean isParallel) (at Library/PackageCache/com.unity.entities@0.8.0-preview.8/Unity.Entities/IJobChunk.cs:212)
Unity.Entities.JobChunkExtensions.Schedule[T] (T jobData, Unity.Entities.EntityQuery query, Unity.Jobs.JobHandle dependsOn) (at Library/PackageCache/com.unity.entities@0.8.0-preview.8/Unity.Entities/IJobChunk.cs:93)
Unity.Transforms.TRSToLocalToWorldSystem.OnUpdate (Unity.Jobs.JobHandle inputDeps) (at Library/PackageCache/com.unity.entities@0.8.0-preview.8/Unity.Transforms/TRSToLocalToWorldSystem.cs:280)
Unity.Entities.JobComponentSystem.Update () (at Library/PackageCache/com.unity.entities@0.8.0-preview.8/Unity.Entities/JobComponentSystem.cs:129)
Unity.Entities.ComponentSystemGroup.UpdateAllSystems () (at Library/PackageCache/com.unity.entities@0.8.0-preview.8/Unity.Entities/ComponentSystemGroup.cs:134)
UnityEngine.Debug:LogException(Exception)
Unity.Debug:LogException(Exception) (at Library/PackageCache/com.unity.entities@0.8.0-preview.8/Unity.Entities/Stubs/Unity/Debug.cs:19)
Unity.Entities.ComponentSystemGroup:UpdateAllSystems() (at Library/PackageCache/com.unity.entities@0.8.0-preview.8/Unity.Entities/ComponentSystemGroup.cs:138)
Unity.Entities.ComponentSystemGroup:OnUpdate() (at Library/PackageCache/com.unity.entities@0.8.0-preview.8/Unity.Entities/ComponentSystemGroup.cs:114)
Unity.Entities.ComponentSystem:Update() (at Library/PackageCache/com.unity.entities@0.8.0-preview.8/Unity.Entities/ComponentSystem.cs:108)
Unity.Entities.ComponentSystemGroup:UpdateAllSystems() (at Library/PackageCache/com.unity.entities@0.8.0-preview.8/Unity.Entities/ComponentSystemGroup.cs:134)
Unity.Entities.ComponentSystemGroup:OnUpdate() (at Library/PackageCache/com.unity.entities@0.8.0-preview.8/Unity.Entities/ComponentSystemGroup.cs:114)
Unity.Entities.ComponentSystem:Update() (at Library/PackageCache/com.unity.entities@0.8.0-preview.8/Unity.Entities/ComponentSystem.cs:108)
Unity.Entities.DummyDelegateWrapper:TriggerUpdate() (at Library/PackageCache/com.unity.entities@0.8.0-preview.8/Unity.Entities/ScriptBehaviourUpdateOrder.cs:152)

Error 4

InvalidOperationException: The system Unity.Rendering.RenderBoundsUpdateSystem reads Unity.Transforms.LocalToWorld via Jobs:CheckStaticBodyChangesJob but that type was not returned as a job dependency. To ensure correct behavior of other systems, the job or a dependency of it must be returned from the OnUpdate method.
Unity.Entities.JobComponentSystem.AfterOnUpdate (Unity.Jobs.JobHandle outputJob, System.Boolean throwException) (at Library/PackageCache/com.unity.entities@0.8.0-preview.8/Unity.Entities/JobComponentSystem.cs:95)
Unity.Entities.JobComponentSystem.Update () (at Library/PackageCache/com.unity.entities@0.8.0-preview.8/Unity.Entities/JobComponentSystem.cs:136)
Unity.Entities.ComponentSystemGroup.UpdateAllSystems () (at Library/PackageCache/com.unity.entities@0.8.0-preview.8/Unity.Entities/ComponentSystemGroup.cs:134)
UnityEngine.Debug:LogException(Exception)
Unity.Debug:LogException(Exception) (at Library/PackageCache/com.unity.entities@0.8.0-preview.8/Unity.Entities/Stubs/Unity/Debug.cs:19)
Unity.Entities.ComponentSystemGroup:UpdateAllSystems() (at Library/PackageCache/com.unity.entities@0.8.0-preview.8/Unity.Entities/ComponentSystemGroup.cs:138)
Unity.Entities.ComponentSystemGroup:OnUpdate() (at Library/PackageCache/com.unity.entities@0.8.0-preview.8/Unity.Entities/ComponentSystemGroup.cs:114)
Unity.Entities.ComponentSystem:Update() (at Library/PackageCache/com.unity.entities@0.8.0-preview.8/Unity.Entities/ComponentSystem.cs:108)
Unity.Entities.ComponentSystemGroup:UpdateAllSystems() (at Library/PackageCache/com.unity.entities@0.8.0-preview.8/Unity.Entities/ComponentSystemGroup.cs:134)
Unity.Entities.ComponentSystemGroup:OnUpdate() (at Library/PackageCache/com.unity.entities@0.8.0-preview.8/Unity.Entities/ComponentSystemGroup.cs:114)
Unity.Entities.ComponentSystem:Update() (at Library/PackageCache/com.unity.entities@0.8.0-preview.8/Unity.Entities/ComponentSystem.cs:108)
Unity.Entities.DummyDelegateWrapper:TriggerUpdate() (at Library/PackageCache/com.unity.entities@0.8.0-preview.8/Unity.Entities/ScriptBehaviourUpdateOrder.cs:152)

What am I missing?

.WithReadOnly(collisionWorld) is currently broken, ie revert back to
IJobForEachWithEntity and using [ReadOnly] which does work

Try this; worked for me

protected override void OnUpdate()
    {
        Dependency = JobHandle.CombineDependencies(m_BuildPhysicsWorldSystem.FinalJobHandle, Dependency);

             RaycastInput RayInput = new RaycastInput
            {
                Start =  Origin,
                End = End,
                Filter = Filter
            };

            CollisionWorld CollisionWorld = m_BuildPhysicsWorldSystem.PhysicsWorld.CollisionWorld;
          
            EntityCommandBuffer CommandBuffer = m_EntityCommandBufferSystem.CreateCommandBuffer();

            JobHandle Job = Job.WithReadOnly(CollisionWorld).WithCode(() =>
            {
                RigidBody? hitBody = null;

                if (CollisionWorld.CastRay(RayInput, out Unity.Physics.RaycastHit hit))
                {
                    // code
                }
              
            }).Schedule(Dependency);

            m_EntityCommandBufferSystem.AddJobHandleForProducer(Job);
        }
    }

I changed my code and it still doesn’t work:

using Unity.Burst;
using Unity.Collections;
using Unity.Entities;
using Unity.Jobs;
using Unity.Physics;
using Unity.Physics.Systems;

    public class DeploymentSystem : JobComponentSystem
    {
        private EntityCommandBufferSystem ecbSystem;
        private EntityQuery cardDefQuery;
        private EntityQuery deployQuery;
        private BuildPhysicsWorld buildPhysicsWorld;

        protected override void OnCreate()
        {
            buildPhysicsWorld = World.GetExistingSystem<BuildPhysicsWorld>();
            ecbSystem = World.GetExistingSystem<EntityCommandBufferSystem>();
            cardDefQuery = GetEntityQuery(ComponentType.ReadOnly<CardDefinition>());
            deployQuery = GetEntityQuery(typeof(DeployTroop));
        }

        protected override JobHandle OnUpdate(JobHandle deps)
        {
            deps = new SpawnJob
            {
                SelectedTroop = GetSingleton<SelectedTroop>(),
                CardDefinitions = cardDefQuery.ToComponentDataArray<CardDefinition>(Allocator.TempJob),
                CommandBuffer = ecbSystem.CreateCommandBuffer().ToConcurrent(),
                CollisionWorld = buildPhysicsWorld.PhysicsWorld.CollisionWorld
            }.Schedule(deployQuery, deps);
          
            ecbSystem.AddJobHandleForProducer(deps);

            return deps;
        }

        [BurstCompile]
        private struct SpawnJob : IJobForEachWithEntity<DeployTroop>
        {
            public EntityCommandBuffer.Concurrent CommandBuffer;
            [ReadOnly] public CollisionWorld CollisionWorld;
            [ReadOnly, DeallocateOnJobCompletion] public NativeArray<CardDefinition> CardDefinitions;
            [ReadOnly] public SelectedTroop SelectedTroop;

            public void Execute(Entity entity, int index, ref DeployTroop deployTroop)
            {
                if (CollisionWorld.CastRay(deployTroop.Raycast, out RaycastHit result))
                {

                }

                CommandBuffer.DestroyEntity(index, entity);
            }
        }
    }

And here is the error:
Error

InvalidOperationException: The previously scheduled job DeploymentSystem:SpawnJob reads from the Unity.Collections.NativeArray1[Unity.Physics.CollisionFilter] SpawnJob.Data.CollisionWorld.Broadphase.m_StaticTree.BodyFilters. You are trying to schedule a new job Broadphase:prepareStaticBodyDataJob, which writes to the same Unity.Collections.NativeArray1[Unity.Physics.CollisionFilter] (via PrepareStaticBodyDataJob.FiltersOut). To guarantee safety, you must include DeploymentSystem:SpawnJob as a dependency of the newly scheduled job.
Unity.Jobs.LowLevel.Unsafe.JobsUtility.ScheduleParallelForDeferArraySize (Unity.Jobs.LowLevel.Unsafe.JobsUtility+JobScheduleParameters& parameters, System.Int32 innerloopBatchCount, System.Void* listData, System.Void* listDataAtomicSafetyHandle) (at :0)

Add something like EndPhysicsFrameSystem.FinalJobHandle to deps before scheduling the job. This indicates this job needs to wait for all the physics jobs to complete. This is not automatic as CollisionWorld is non ComponentData. For good measure also add [UpdateAfter(typeof(EndFramePhysicsSystem))] to the system. Finally use SystemBase as baseclass and add the dependency like so

Dependency = JobHandle.CombineDependencies(Dependency, EndPhysicsFrameSystem.FinalJobHandle)
1 Like

btw, if you prefer you can patch the physics package, copy it in to your project to stop it form reverting and apply the fix, see this thread Physics World in Collision Job broken in 0.3.1

What is the correct way in Unity.Physics.0.5.0-preview.1? I am still receiving this error

using Domain.Components;
using Unity.Entities;
using Unity.Jobs;
using Unity.Physics;
using Unity.Physics.Systems;

namespace Domain.Systems
{
[UpdateAfter(typeof(BuildPhysicsWorld))]
public class RaycastSystem : SystemBase
{
  private BuildPhysicsWorld     buildPhysicsWorld;
  private EndFramePhysicsSystem endFramePhysicsSystem;

  protected override void OnCreate()
  {
   buildPhysicsWorld     = World.GetOrCreateSystem<BuildPhysicsWorld>();
   endFramePhysicsSystem = World.GetOrCreateSystem<EndFramePhysicsSystem>();
  }

  protected override void OnUpdate()
  {
   CollisionWorld collisionWorld = buildPhysicsWorld.PhysicsWorld.CollisionWorld;
   Dependency = JobHandle.CombineDependencies(Dependency, endFramePhysicsSystem.GetOutputDependency());
   
   Dependency = Entities.WithName(nameof(RaycastSystem))
    .ForEach((ref RaycastRequest request) =>
    {
     if (request.Completed)
      return;
     if (!request.ConsideredBeforeBuildPhysicsWorld)
      return;

     request.Hit           = collisionWorld.CastRay(request.RaycastInput, out RaycastHit closestHit);
     request.RaycastResult = closestHit;
     request.Completed     = true;
    })
    .Schedule(Dependency);
   Dependency.Complete();
  }
}
}

Although I am both adding EndFramePhysicsSystem, to run after all colliders are created, as well as completing immediatly.

Do you have [UpdateBefore(typeof(BuildPhysicsWorld))] at the top of your class?

@brunocoimbra I have used [UpdateAfter(typeof(BuildPhysicsWorld)] as the goal was to have these in order:

  • PhysicsCollider Creation
  • Update Physics World
  • Execute Raycast against colliders created

Then you need to use [UpdateAfter(typeof(EndFramePhysicsSystem))] instead.

if you use [UpdateAfter(typeof(BuildPhysicsWorld))]
you input dependency needs to be
JobHandle.CombineDependencies(Dependency, buildPhysicsWorld.GetOutputDependency());
and you had better add you output dependency to endFramePhysicsSystem endFramePhysicsSystem.AddInputDependency(yoursystemdependency)