How to raycast from a system job?

None of the samples seem to have this basic case. Both the query sample and the raycast car demo runs raycast jobs and completes them immediately. I am attempting to cast a ray and I keep getting scheduling errors. I found this gist as a guide, but nothing I try works

[GenerateAuthoringComponent]
public struct RaycastData : IComponentData
{
    public bool hasHit;
}

[UpdateAfter(typeof(BuildPhysicsWorld)), UpdateBefore(typeof(EndFramePhysicsSystem))]
public class RaycastFromSystem : JobComponentSystem
{
    BuildPhysicsWorld bpWorld;
    EndFramePhysicsSystem endFramePhysicsSystem;

    protected override void OnStartRunning()
    {
        bpWorld = World.GetExistingSystem<BuildPhysicsWorld>();
        endFramePhysicsSystem = World.GetExistingSystem<EndFramePhysicsSystem>();
    }

    protected override JobHandle OnUpdate(JobHandle inputDeps)
    {
        ref PhysicsWorld pWorld = ref bpWorld.PhysicsWorld;

        inputDeps = JobHandle.CombineDependencies(inputDeps, bpWorld.FinalJobHandle);

        CollisionWorld cw = pWorld.CollisionWorld;

        JobHandle handle = Entities.WithName("HitTest")
            .ForEach((ref Translation pos, ref RaycastData data) =>
        {
            RaycastInput rinput = new RaycastInput()
            {
                Start = pos.Value,
                End = pos.Value - up()
            };

            data.hasHit = cw.CastRay(rinput);

        }).Schedule(inputDeps);

        endFramePhysicsSystem.HandlesToWaitFor.Add(handle);

        return handle;
    }
}

I keep getting:

InvalidOperationException: The previously scheduled job RaycastFromSystem:<>c__DisplayClass_HitTest writes to the NativeArray <>c__DisplayClass_HitTest.Data.cw.Broadphase.m_DynamicTree.m_BranchCount. You are trying to schedule a new job Broadphase:AllocateDynamicVsStaticNodePairs, which reads from the same NativeArray (via AllocateDynamicVsStaticNodePairs.dynamicBranchCount). To guarantee safety, you must include RaycastFromSystem:<>c__DisplayClass_HitTest as a dependency of the newly scheduled job.

I did add the handle to the EndFramePhysicsSystem, but it still complains.

Additionally, I noticed that the physics sample uses a [ReadOnly] on PhysicsWorld in the raycast job (here), but the thing is that lambda function .WithReadOnly(physicsWorld) does not support that because it "can only be called with an argument that is marked with [NativeContainerAttribute]". Is the [ReadOnly] on PhysicsWorld in the sample just a placebo or does it actually do anything?

Hey @Nothke . It is indeed an issue that we only allow WithReadOnly on Native Container types (and not also types that contain Native Containers). That restriction will be fixed in the next version of Entities.

3 Likes


Was this already fixed, if yes starting at which version of which package could I expect the fix to work?

We definitely need to look at some demos for this use-case.

@Nothke that looks like an older version of Unity Physics if you are still using HandlesToWaitFor. In 0.4.0-preview.5, we added AddInputDependency and GetOutputDependency functions for the Physics Systems to be able to chain dependencies more accurately, though this might not help your case here. BuildPhysicsWorld also got a AddInputDependencyToComplete function for jobs that need to be completed before the CollisionWorld gets reset and rebuilt.

The current RayTracer sample code does Complete the raycast jobs as well, but I've attached a version that doesn't. I don't believe the Complete in the associated MonoBehaviour should be needed because of the IsCompleted check but if I don't add it the JobsDebugger throws up the usual scheduling errors.

6531473--737738--RayTracer.zip (4.76 KB)

2 Likes


The IsCompleted pattern would be awsome if it would allow to run for more than one frame. Any idea on how to extend it to multiple frames?

No matter what, I still wanted to thank you as that example has helped me a lot with Raycasts questions I have posted lately.

1 Like

The broadphase could change from frame to frame, so if you need to run a multi-frame raycast you should really just clone the CollisionWorld and raycast against that snapshot.

[EDIT] Note that while the clone could help, the referenced colliders could still be tweaked e.g. the collisionfilters changed over different frame so results could lead to interesting race conditions.

Can I ask what is the use case for multi-frame raycasts? Actually, I ask again on this thread: Help Wanted - How to raycast from a system job? - Unity Forum

1 Like

[quote=“steveeHavok”, post:6, topic: 778588]
The broadphase could change from frame to frame, so if you need to run a multi-frame raycast you should really just clone the CollisionWorld and raycast against that snapshot.

[EDIT] Note that while the clone could help, the referenced colliders could still be tweaked e.g. the collisionfilters changed over different frame so results could lead to interesting race conditions.

Can I ask what is the use case for multi-frame raycasts? Actually, I ask again on this thread: Help Wanted - How to raycast from a system job? - Unity Forum
[/quote]
Pretty much anything with a close to static collision world (e.g. only changing on specific user interactions) but huge amounts of raycasts.

If world does only change very rarely, but you really want to do many physic checks (Raycasts just beeing the most common one e.g. explorative sciences, sound/light wave simulations, whatever …). This means my code has to split the raycasts into batches, where each batch fits into a single frame. This means every frame I either schedule too many or too little raycasts that I could have scheduled without making the UI unresponsive. Let’s say every few raycasts the result already would have more information and the user could gain more insights but all raycasts together will run for minutes or even hours, and the user only cancels ones he gives up.

2 Likes