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.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

ICollisionEventsJob not detecting collisions despite the Scene clearly demonstrating collisions

Discussion in 'Physics for ECS' started by Abbrew, Mar 29, 2020.

  1. Abbrew

    Abbrew

    Joined:
    Jan 1, 2018
    Posts:
    417
    I've tried:
    • checking the collision matrix under Project Settings
    • ensuring that the Rigidbody and Box Collider are configured correctly (no isTrigger, isKinematic, etc)
    • checking that Convert To Entity is added
    • checking that the system runs after StepPhysicsWorld and before EndFramePhysicsSystem
    • creating a default Cube and attaching to it RigidBody and Convert To Entity, then dropping it onto an isKinematic terrain with a normal Collider
    Here's the code

    Code (CSharp):
    1. using Unity.Entities;
    2. using Unity.Physics;
    3. using Unity.Burst;
    4. using Unity.Collections;
    5. using UnityEngine;
    6.  
    7. public class NoiseMakerItemPhysicalSystem : PhysicsDetectJobComponentSystem
    8. {
    9.     private EntityCommandBufferSystem endFrame;
    10.  
    11.     protected override void OnUpdate()
    12.     {
    13.         base.OnUpdate();
    14.  
    15.         var noiseMakersQueue = new NativeQueue<Entity>(Allocator.TempJob);
    16.  
    17.         Dependency = new FirstTimeCollidingJob
    18.         {
    19.             noiseMakersQueue = noiseMakersQueue.AsParallelWriter(),
    20.             groundedFromEntity = GetComponentDataFromEntity<NoiseMakerItemPhysicalGroundedComponent>(true),
    21.             noiseMakerFromEntity = GetComponentDataFromEntity<NoiseMakerItemPhysicalComponent>(true)
    22.         }.Schedule(stepPhysicsWorld.Simulation, ref buildPhysicsWorld.PhysicsWorld, Dependency);
    23.  
    24.         var ecb = endFrame.CreateCommandBuffer();
    25.  
    26.         Job
    27.             .WithCode(() =>
    28.             {
    29.                 while(noiseMakersQueue.TryDequeue(out var noiseMakerEntity))
    30.                 {
    31.                     ecb.AddComponent(noiseMakerEntity, new NoiseMakerItemPhysicalGroundedComponent());
    32.  
    33.                     var messageEntity = ecb.CreateEntity();
    34.                     ecb.AddComponent(messageEntity, new NoiseMakerItemPingMessageComponent
    35.                     {
    36.                         noiseMakerEntity = noiseMakerEntity
    37.                     });
    38.                     ecb.AddComponent(messageEntity, new MessagingEnd());
    39.                 }
    40.             }).Schedule();
    41.  
    42.         Dependency = noiseMakersQueue.Dispose(Dependency);
    43.  
    44.         endFrame.AddJobHandleForProducer(Dependency);
    45.     }
    46.  
    47.     [BurstCompile]
    48.     private struct FirstTimeCollidingJob : ICollisionEventsJob
    49.     {
    50.         [ReadOnly]
    51.         public ComponentDataFromEntity<NoiseMakerItemPhysicalComponent> noiseMakerFromEntity;
    52.         [ReadOnly]
    53.         public ComponentDataFromEntity<NoiseMakerItemPhysicalGroundedComponent> groundedFromEntity;
    54.  
    55.         [WriteOnly]
    56.         public NativeQueue<Entity>.ParallelWriter noiseMakersQueue;
    57.  
    58.         public void Execute(CollisionEvent collisionEvent)
    59.         {
    60.             Debug.Log("any collision: " );
    61.  
    62.             var entities = collisionEvent.Entities;
    63.             var entityA = entities.EntityA;
    64.  
    65.             if (noiseMakerFromEntity.Exists(entityA) && !groundedFromEntity.Exists(entityA))
    66.             {
    67.                 //Debug.Log("First bounce");
    68.                 noiseMakersQueue.Enqueue(entityA);
    69.             }
    70.             var entityB = entities.EntityB;
    71.             if (noiseMakerFromEntity.Exists(entityB) && !groundedFromEntity.Exists(entityB))
    72.             {
    73.                 //Debug.Log("First bounce");
    74.                 noiseMakersQueue.Enqueue(entityB);
    75.             }
    76.  
    77.             //Debug.Log("any collision: " + entityA + " " + entityB);
    78.         }
    79.     }
    80.  
    81.     protected override void OnCreate()
    82.     {
    83.         base.OnCreate();
    84.  
    85.         endFrame = World.GetOrCreateSystem<EndSimulationEntityCommandBufferSystem>();
    86.     }
    87. }
    88.  
    Code (CSharp):
    1. using Unity.Entities;
    2. using Unity.Physics.Systems;
    3.  
    4. [UpdateAfter(typeof(StepPhysicsWorld))]
    5. [UpdateBefore(typeof(EndFramePhysicsSystem))]
    6. public abstract class PhysicsDetectJobComponentSystem : SystemBase
    7. {
    8.     protected BuildPhysicsWorld buildPhysicsWorld;
    9.     protected StepPhysicsWorld stepPhysicsWorld;
    10.     protected EndFramePhysicsSystem endFramePhysics;
    11.  
    12.     protected override void OnUpdate()
    13.     {
    14.         stepPhysicsWorld.FinalJobHandle.Complete();
    15.     }
    16.  
    17.     protected override void OnCreate()
    18.     {
    19.         buildPhysicsWorld = World.GetOrCreateSystem<BuildPhysicsWorld>();
    20.         stepPhysicsWorld = World.GetOrCreateSystem<StepPhysicsWorld>();
    21.         endFramePhysics = World.GetOrCreateSystem<EndFramePhysicsSystem>();
    22.     }
    23. }
    24.  
     
  2. Rory_Havok

    Rory_Havok

    Joined:
    Jun 25, 2018
    Posts:
    70
    Have you enabled the "Raise Collision Events" flag on your colliders? This is off by default, you must opt-into it for any colliders that you are interested in.
     
    Abbrew likes this.
  3. Abbrew

    Abbrew

    Joined:
    Jan 1, 2018
    Posts:
    417
    Thank you, I found it on the PhysicsBody authoring. That was the issue for me. This means that I'll have to overhaul the section of my codebase dealing with physics layers though. The PhysicsCategoryNames - can they be accessed through code? I want to be able to programmatically merge layer masks and expose them from a manager class, like so:

    Code (CSharp):
    1. [Serializable]
    2. public struct EnvironmentData
    3. {
    4.     [Header("Layers")]
    5.     public LayerMask staticObstacles;
    6.     public LayerMask staticObstaclesPhaseable;
    7.     public LayerMask dynamicObstacles;
    8.     public LayerMask transientObstacles;
    9.     public LayerMask terrain;
    10.     public LayerMask unwalkableMarkers;
    11.     public LayerMask speedModifierMarkers;
    12.     public LayerMask opaqueCover;
    13.     public LayerMask translucentCover;
    14.     public LayerMask humanoid;
    15.  
    16.     public LayerMask GetSpeedModifier()
    17.     {
    18.         return speedModifierMarkers;
    19.     }
    20.  
    21.     public LayerMask GetUnwalkable()
    22.     {
    23.         return unwalkableMarkers;
    24.     }
    25.  
    26.     public LayerMask GetOpaque()
    27.     {
    28.         return staticObstacles | staticObstaclesPhaseable | terrain;
    29.     }
    30.  
    31.     public LayerMask GetSurface()
    32.     {
    33.         return staticObstacles | terrain | opaqueCover | translucentCover;
    34.     }
    35.  
    36.     public LayerMask GetEvaluatedAsCover()
    37.     {
    38.         return  opaqueCover | terrain;
    39.     }
    40.  
    41.     public LayerMask GetDestinationLightCover()
    42.     {
    43.         return translucentCover | opaqueCover | terrain;
    44.     }
    45.  
    46.     public LayerMask GetMapCover()
    47.     {
    48.         return translucentCover | opaqueCover | terrain;
    49.     }
    50.  
    51.     public LayerMask GetWaypointsConservativeCover()
    52.     {
    53.         return GetEvaluatedAsCover() | transientObstacles;
    54.     }
    55.  
    56.     public LayerMask GetObstacle()
    57.     {
    58.         return staticObstacles | transientObstacles | staticObstaclesPhaseable
    59.             | opaqueCover | translucentCover | terrain | dynamicObstacles | humanoid;
    60.     }
    61.  
    62.     public LayerMask GetVisible()
    63.     {
    64.         return staticObstacles | transientObstacles | staticObstaclesPhaseable
    65.             | terrain | dynamicObstacles;
    66.     }
    67.  
    68.     public LayerMask GetVisibleBlockers()
    69.     {
    70.         return GetVisible();
    71.     }
    72.  
    73.     public LayerMask GetAll()
    74.     {
    75.         return ~0;
    76.     }
     
  4. Adam-Mechtley

    Adam-Mechtley

    Unity Technologies

    Joined:
    Feb 5, 2007
    Posts:
    290
    Late reply here, but: In general you should serialize authoring data using the PhysicsCategoryTags struct (which will give you a nice selector in the UI) and then you can just use its Value property during conversion and merge as normal using bitwise operators.
     
    Abbrew and florianhanke like this.