How do I raycast in an old state of the world inside a job running for several frames?

I’m still new to Entities and thought the SSCCE below would work:

public class MyTestComponent : UnityEngine.MonoBehaviour {
 
    private MyTest job;
    private Unity.Jobs.JobHandle handle;

    void FixedUpdate() {
        handle.Complete();
        Unity.Physics.Systems.BuildPhysicsWorld buildPhysicsWorld = Unity.Entities.World.DefaultGameObjectInjectionWorld.GetExistingSystem<Unity.Physics.Systems.BuildPhysicsWorld>();
        job.cw = buildPhysicsWorld.PhysicsWorld.CollisionWorld;
        handle = Unity.Jobs.IJobParallelForExtensions.Schedule<MyTest>(job, 500, 50);
    }

}

public struct MyTest : Unity.Jobs.IJobParallelFor {
    [Unity.Collections.ReadOnly]
    public Unity.Physics.CollisionWorld cw;
    public void Execute(int index) {
        //do nothing for now, planning to do cw.CastRay()
    }
}

However I’m getting:
InvalidOperationException: The previously scheduled job MyTest reads from the NativeArray MyTest.cw.m_Bodies. You must call JobHandle.Complete() on the job MyTest, before you can deallocate the NativeArray safely.

If I move handle.Complete(); to the end of FixedUpdate() everything works but not if have it in the beginning like I need. I want to have units in my game raycast their vision from their predicted future positions next keyframe, then simply apply the vision when the keyframe is reached. That’s why I need to raycast an old state of the world for several frames, it can’t just finish on the same frame.

How am I supposed to do this?
Do I need to call some kind of “make permanent copy” method instead of using .PhysicsWorld.CollisionWorld?

I think CollisionWorld.Clone() is what you need in your example. Let me know if it works for you!

3 Likes

@petarmHavok : That hit the spot, thank you! Working code below.

public class MyTestComponent : UnityEngine.MonoBehaviour {
 
    private MyTest job;
    private Unity.Jobs.JobHandle handle;

    void FixedUpdate() {
        OnDestroy();  //modified line
        Unity.Physics.Systems.BuildPhysicsWorld buildPhysicsWorld = Unity.Entities.World.DefaultGameObjectInjectionWorld.GetExistingSystem<Unity.Physics.Systems.BuildPhysicsWorld>();
        job.cw = buildPhysicsWorld.PhysicsWorld.CollisionWorld.Clone();  //modified line
        handle = Unity.Jobs.IJobParallelForExtensions.Schedule<MyTest>(job, 500, 50);
    }

    void OnDestroy() {  //new method
        handle.Complete();
        job.cw.Dispose();
    }

}

public struct MyTest : Unity.Jobs.IJobParallelFor {
    [Unity.Collections.ReadOnly]
    public Unity.Physics.CollisionWorld cw;
    public void Execute(int index) {
        //do nothing for now, planning to do cw.CastRay()
    }
}
1 Like