Search Unity

Question How to Schedule a Raycast in a C# Job for Entities Generated at Runtime

Discussion in 'Physics for ECS' started by AScaredyCat, May 15, 2022.

  1. AScaredyCat

    AScaredyCat

    Joined:
    Dec 31, 2020
    Posts:
    12
    [Unity 2020.2.1f1 | Entities 0.17.0-preview.42 | Unity Physics 0.6.0-preview.3]

    Problem:
    I have a scene that generates terrain in a C# Job constructed out of modular terrain pieces (runtime entities) when a ui button is pressed, this part all works as expected. I then need to perform some additional operations on those entities via Raycast. I followed the documentation and my Raycasts also work fine, except if I want the results in the same frame the entities are instantiated. For example, if I wait a frame or two then try, the Raycast works as expected. If I Raycast on the frame of instantiation they hit nothing, hence the suspected scheduling issue.

    I know from research that the Raycast Job needs to be scheduled at a certain time during the physics step otherwise the results will be off by a frame, but I am struggling to find documentation/examples that show how to deal with entities generated at runtime. For reference, the entities being cast against are instantiated from a Read Only NativeArray of source entities via an IJobParallelFor, and their transforms are set via a ParallelWriter EntityCommandBuffer.

    Attempted Solutions:
    - I've attempted to tag my C# Job Structs (the IJobParallelFor) with [UpdateInGroup], [UpdateBefore], and [UpdateAfter] attributes (in addition to [BurstCompile]) to try and set when they need to run but have not found a set that works the same frame as the entities are instantiated.
    - I supplied the JobHandle for the Job that instantiates the terrain to the Raycast Job as a dependency and call Complete before attempting the Raycast Job but this also did not work the same frame.
    - I've also added the instantiation Job as an input dependency to the BuildPhysicsWorld (via: buildPhysicsWorld.AddInputDependency(jobHandle); ) but this also didn't change the outcome.

    Im vaguely aware of what the BroadPhase is, and its importance to Raycasting. Im pretty sure i need to instantiate my entities before the BroadPhase is set for the frame but again Im not super knowledgeable about that.

    To reiterate, this all done via C# Jobs being called from the main thread after a ui button is pressed. The Jobs are tagged and their handles are being fed to each other as dependencies but i still have to wait a frame or two to raycast against the entities generated by them.

    Questions:
    1. Is waiting until the next frame the intended behavior for casting against runtime entities?
    2. Is there a way to schedule the C# Jobs (instantiation job -> raycast job) such that the Raycast Job can operate after the Instantiation Job on the same frame?
    3. Are there any resources (besides the manual) that you have found helpful in understanding Scheduling C# Jobs? (links appreciated <3 )

    Sorry if this is a lot, I've been stumped by this for a bit so any push in the right direction would be super appreciated ^-^ If you need more info to help with my issue please let me know!
     
  2. AScaredyCat

    AScaredyCat

    Joined:
    Dec 31, 2020
    Posts:
    12
    Okay so an old post of mine asking a similar question actually already had some pointers to some of my questions >.<

    That led me to looking up PhysicsStep.SynchronizeCollisionWorld which led me finding this info in the Change Log ([0.4.0-preview.5] - 2020-06-18) of the Unity.Physics Package:
    • (added) PhysicsStep.SynchronizeCollisionWorld to enable rebuild of the dynamic bodies bounding volume hierarchy after the step. This enables precise query results before the next BuildPhysicsWorld update call. Note that BuildPhysicsWorld will do this work on the following frame anyway, so only use this option when another system must know about the results of the simulation before the end of the frame (e.g., to destroy or create some other body that must be present in the following frame). In most cases, tolerating a frame of latency is easier to work with and is better for performance.
    As a result:
    1.Yes, waiting for a frame to cast against dynamic entities is intended especially if performance is a concern, but there is another way. (This isn't made especially clear anywhere in documentation outside the change logs but is super good to know!)

    2. Yes, but scheduling them really wasn't the issue (they were already setup in that order anyway), it was actually knowing that you can set PhysicsStep.SynchronizeCollisionWorld to force the broadphase to update this frame.

    This leaves me with a new question:
    1a. How do you properly set the PhysicsStep's properties? I attempted to set SynchronizeCollisionWorld both in the C# Job itself, at the start of the scene, but neither one worked. The result was the same, and no raycasts found their targets. It seems straight forward since its just a struct but i think i might need to feed that struct to something to update the new settings, but the documentation surrounding SychronizeCollisionWorld has little info.

    Any help with this remaining question (and any resources for understanding scheduling better) would of course be super appreciated! ^-^