Search Unity

Question How to raycast from a system job?

Discussion in 'Physics for ECS' started by Nothke, Feb 27, 2020.

  1. Nothke

    Nothke

    Joined:
    Dec 2, 2012
    Posts:
    112
    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

    Code (CSharp):
    1. [GenerateAuthoringComponent]
    2. public struct RaycastData : IComponentData
    3. {
    4.     public bool hasHit;
    5. }
    6.  
    7. [UpdateAfter(typeof(BuildPhysicsWorld)), UpdateBefore(typeof(EndFramePhysicsSystem))]
    8. public class RaycastFromSystem : JobComponentSystem
    9. {
    10.     BuildPhysicsWorld bpWorld;
    11.     EndFramePhysicsSystem endFramePhysicsSystem;
    12.  
    13.     protected override void OnStartRunning()
    14.     {
    15.         bpWorld = World.GetExistingSystem<BuildPhysicsWorld>();
    16.         endFramePhysicsSystem = World.GetExistingSystem<EndFramePhysicsSystem>();
    17.     }
    18.  
    19.     protected override JobHandle OnUpdate(JobHandle inputDeps)
    20.     {
    21.         ref PhysicsWorld pWorld = ref bpWorld.PhysicsWorld;
    22.  
    23.         inputDeps = JobHandle.CombineDependencies(inputDeps, bpWorld.FinalJobHandle);
    24.  
    25.         CollisionWorld cw = pWorld.CollisionWorld;
    26.      
    27.         JobHandle handle = Entities.WithName("HitTest")
    28.             .ForEach((ref Translation pos, ref RaycastData data) =>
    29.         {
    30.             RaycastInput rinput = new RaycastInput()
    31.             {
    32.                 Start = pos.Value,
    33.                 End = pos.Value - up()
    34.             };
    35.  
    36.             data.hasHit = cw.CastRay(rinput);
    37.  
    38.         }).Schedule(inputDeps);
    39.  
    40.         endFramePhysicsSystem.HandlesToWaitFor.Add(handle);
    41.  
    42.         return handle;
    43.     }
    44. }
    I keep getting:
    Code (csharp):
    1. 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?
     
    Last edited: Feb 27, 2020
  2. joepl

    joepl

    Unity Technologies

    Joined:
    Jul 6, 2017
    Posts:
    87
    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.
     
    florianhanke, NotaNaN and Nothke like this.
  3. MNNoxMortem

    MNNoxMortem

    Joined:
    Sep 11, 2016
    Posts:
    723
    Was this already fixed, if yes starting at which version of which package could I expect the fix to work?
     
  4. steveeHavok

    steveeHavok

    Joined:
    Mar 19, 2019
    Posts:
    481
    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.
     

    Attached Files:

    Wobbers and MNNoxMortem like this.
  5. MNNoxMortem

    MNNoxMortem

    Joined:
    Sep 11, 2016
    Posts:
    723
    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.
     
    petarmHavok likes this.
  6. steveeHavok

    steveeHavok

    Joined:
    Mar 19, 2019
    Posts:
    481
    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
     
    Last edited: Nov 24, 2020
    MNNoxMortem likes this.
  7. MNNoxMortem

    MNNoxMortem

    Joined:
    Sep 11, 2016
    Posts:
    723
    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.
     
    steveeHavok and petarmHavok like this.