Search Unity

  1. Unity Asset Manager is now available in public beta. Try it out now and join the conversation here in the forums.
    Dismiss Notice
  2. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  3. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Question Trouble getting CollisionWorld.CalculateDistance() to work.

Discussion in 'Physics Previews' started by BenMM, Nov 13, 2020.

  1. BenMM

    BenMM

    Joined:
    Jan 28, 2019
    Posts:
    16
    Hi,
    I am trying to get all enemys in a certain range around my tower into its Dynamic buffer.
    but "CollisionWorld.CalculateDistance()" either doesnt work at all, works but throws a plethera of errors or Works when using without burst and with run instead of schedule parallel.

    I'm unsure as to how to fix the issue.

    Code (CSharp):
    1.  
    2. public class TargetingSystem : SystemBase
    3. {
    4.     private BuildPhysicsWorld buildPhysicsWorld;
    5.     private EndFramePhysicsSystem endFramePhysicsSystem;
    6.  
    7.     protected override void OnCreate()
    8.     {
    9.         this.buildPhysicsWorld = World.GetExistingSystem<BuildPhysicsWorld>();
    10.         this.endFramePhysicsSystem = World.GetExistingSystem<EndFramePhysicsSystem>();
    11.     }
    12.  
    13.     protected override void OnUpdate()
    14.     {
    15.         var collisionWorld = this.buildPhysicsWorld.PhysicsWorld.CollisionWorld;
    16.         this.Dependency =
    17.             JobHandle.CombineDependencies(this.Dependency, this.endFramePhysicsSystem.GetOutputDependency());
    18.  
    19.  
    20.         Entities.WithAll<TagTower>().WithBurst().ForEach((ref DynamicBuffer<Target> targets) =>
    21.         {
    22.             var hits = new NativeList<DistanceHit>(Allocator.Temp);
    23.  
    24.             var filter = new CollisionFilter()
    25.             {
    26.                 BelongsTo = ~0u,
    27.                 CollidesWith = ~0u,
    28.                 GroupIndex = 0
    29.             };
    30.  
    31.             var distanceInput = new PointDistanceInput()
    32.             {
    33.                 Position = float3.zero,
    34.                 MaxDistance = 10f,
    35.                 Filter = filter
    36.             };
    37.  
    38.             collisionWorld.CalculateDistance(distanceInput, ref hits);
    39.  
    40.             for (int i = 0; i < hits.Length; i++)
    41.             {
    42.                 Debug.Log("Location:  " + hits[i].Position);
    43.                 Debug.Log("Entity:  " + hits[i].Entity);
    44.             }
    45.  
    46.             hits.Dispose();
    47.         }).ScheduleParallel();
    48.     }
    49. }

    This returns the expected results, but returns the following errors:
    (Removing "collisionWorld.CalculateDistance(distanceInput, ref hits);" resolves all errors)


    A Native Collection has not been disposed, resulting in a memory leak. Enable Full StackTraces to get more details.

    InvalidOperationException: The previously scheduled job TargetingSystem:<>c__DisplayClass_OnUpdate_LambdaJob0 writes to the Unity.Collections.NativeArray`1[Unity.Physics.CollisionFilter] <>c__DisplayClass_OnUpdate_LambdaJob0.JobData.collisionWorld.Broadphase.m_StaticTree.BodyFilters. You are trying to schedule a new job Broadphase: PrepareStaticBodyDataJob, which writes to the same Unity.Collections.NativeArray`1[Unity.Physics.CollisionFilter] (via PrepareStaticBodyDataJob.FiltersOut). To guarantee safety, you must include TargetingS

    InvalidOperationException: The previously scheduled job TargetingSystem:<>c__DisplayClass_OnUpdate_LambdaJob0 writes to the Unity.Collections.NativeArray`1[System.Int32] <>c__DisplayClass_OnUpdate_LambdaJob0.JobData.collisionWorld.Broadphase.m_DynamicTree.BranchCount. You are trying to schedule a new job Broadphase:AllocateDynamicVsStaticNodePairs, which reads from the same Unity.Collections.NativeArray`1[System.Int32] (via AllocateDynamicVsStaticNodePairs.dynamicBranchCount). To guarantee safety, you must include TargetingSystem:<>

    InvalidOperationException: Adding/removing components or changing position/rotation/velocity/collider ECS data on dynamic entities during physics step

    InvalidOperationException: The previously scheduled job Broadphase: PrepareNumStaticBodiesJob writes to the Unity.Collections.NativeArray`1[System.Int32] PrepareNumStaticBodiesJob.BuildStaticTree. You must call JobHandle.Complete() on the job Broadphase: PrepareNumStaticBodiesJob, before you can write to the Unity.Collections.NativeArray`1[System.Int32] safely.

    If i declare CollisionWorld in OnCreate instead of OnUpdate:

    Code (CSharp):
    1.  
    2. public class TargetingSystem : SystemBase
    3. {
    4.     private BuildPhysicsWorld buildPhysicsWorld;
    5.     private EndFramePhysicsSystem endFramePhysicsSystem;
    6.     private CollisionWorld collisionWorld;
    7.  
    8.     protected override void OnCreate()
    9.     {
    10.         this.buildPhysicsWorld = World.GetExistingSystem<BuildPhysicsWorld>();
    11.         this.endFramePhysicsSystem = World.GetExistingSystem<EndFramePhysicsSystem>();
    12.         collisionWorld = this.buildPhysicsWorld.PhysicsWorld.CollisionWorld;
    13.     }
    14.  

    The error tells me to use

    Entities.ForEach Lambda expression uses field 'collisionWorld'. Either assign the field to a local outside of the lambda expression and use that instead, or use .WithoutBurst() and .Run()

    Doing that works fine and i get the expected results without errors.

    Is there a way to run this in Parallel without getting all these errors?




     

    Attached Files:

    Last edited: Nov 13, 2020
  2. petarmHavok

    petarmHavok

    Joined:
    Nov 20, 2018
    Posts:
    461
    I'm gonna try and help you with the original approach to make this work in parallel. You are missing 2 things:

    1. You need
    [UpdateInGroup(typeof(FixedStepSimulationSystemGroup))]
    [UpdateAfter(typeof(EndFramePhysicsSystem))]
    to make sure your system updates at the exact time.
    2. You also need
    buildPhysicsWorld.AddDependencyToComplete(Dependency)
    at the very end of your OnUpdate() method to inform the BuildPhysicsWorld of the next step that it needs to wait for your jobs to finish.

    Let's start with these 2 and see if there are more changes needed. We can also look into scheduling this at different times (after step, before export or similar).
     
    MNNoxMortem likes this.