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.

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

Discussion in 'Physics for ECS' started by Interjection, Jul 17, 2020.

  1. Interjection

    Interjection

    Joined:
    Jun 18, 2020
    Posts:
    63
    I'm still new to Entities and thought the SSCCE below would work:

    Code (CSharp):
    1. public class MyTestComponent : UnityEngine.MonoBehaviour {
    2.  
    3.     private MyTest job;
    4.     private Unity.Jobs.JobHandle handle;
    5.  
    6.     void FixedUpdate() {
    7.         handle.Complete();
    8.         Unity.Physics.Systems.BuildPhysicsWorld buildPhysicsWorld = Unity.Entities.World.DefaultGameObjectInjectionWorld.GetExistingSystem<Unity.Physics.Systems.BuildPhysicsWorld>();
    9.         job.cw = buildPhysicsWorld.PhysicsWorld.CollisionWorld;
    10.         handle = Unity.Jobs.IJobParallelForExtensions.Schedule<MyTest>(job, 500, 50);
    11.     }
    12.  
    13. }
    14.  
    15. public struct MyTest : Unity.Jobs.IJobParallelFor {
    16.     [Unity.Collections.ReadOnly]
    17.     public Unity.Physics.CollisionWorld cw;
    18.     public void Execute(int index) {
    19.         //do nothing for now, planning to do cw.CastRay()
    20.     }
    21. }
    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
    ?
     
  2. petarmHavok

    petarmHavok

    Joined:
    Nov 20, 2018
    Posts:
    461
    I think CollisionWorld.Clone() is what you need in your example. Let me know if it works for you!
     
  3. Interjection

    Interjection

    Joined:
    Jun 18, 2020
    Posts:
    63
    @petarmHavok: That hit the spot, thank you! Working code below.

    Code (CSharp):
    1. public class MyTestComponent : UnityEngine.MonoBehaviour {
    2.  
    3.     private MyTest job;
    4.     private Unity.Jobs.JobHandle handle;
    5.  
    6.     void FixedUpdate() {
    7.         OnDestroy();  //modified line
    8.         Unity.Physics.Systems.BuildPhysicsWorld buildPhysicsWorld = Unity.Entities.World.DefaultGameObjectInjectionWorld.GetExistingSystem<Unity.Physics.Systems.BuildPhysicsWorld>();
    9.         job.cw = buildPhysicsWorld.PhysicsWorld.CollisionWorld.Clone();  //modified line
    10.         handle = Unity.Jobs.IJobParallelForExtensions.Schedule<MyTest>(job, 500, 50);
    11.     }
    12.  
    13.     void OnDestroy() {  //new method
    14.         handle.Complete();
    15.         job.cw.Dispose();
    16.     }
    17.  
    18. }
    19.  
    20. public struct MyTest : Unity.Jobs.IJobParallelFor {
    21.     [Unity.Collections.ReadOnly]
    22.     public Unity.Physics.CollisionWorld cw;
    23.     public void Execute(int index) {
    24.         //do nothing for now, planning to do cw.CastRay()
    25.     }
    26. }
     
    petarmHavok likes this.