Search Unity

How to Detect Collisions with Unity.Physics ?

Discussion in 'Data Oriented Technology Stack' started by MixGrey, Sep 11, 2019.

  1. MixGrey

    MixGrey

    Joined:
    Dec 23, 2014
    Posts:
    9
    Some outdated examples show the use of a "CollisionEvents" from StepPhysicsWorld, but this is no longer accessible. Supposedly an ICollisionEventsJob can be used, but it doesn't seem to do anything.

    The physics simulation in my project works, the objects bounce off of each other, and my CollisionSystem runs, but my CollisionJob never gets any collision events.

    Code (CSharp):
    1. [UpdateAfter(typeof(StepPhysicsWorld))]
    2.     [UpdateBefore(typeof(EndFramePhysicsSystem))]
    3.     public class CollisionSystem : JobComponentSystem
    4.     {
    5.  
    6.         struct CollisionJob : ICollisionEventsJob
    7.         {
    8.             [ReadOnly] public PhysicsWorld physicsWorld;
    9.  
    10.             public void Execute(CollisionEvent ev) // this is never called
    11.             {
    12.                 Entity a = physicsWorld.Bodies[ev.BodyIndices.BodyAIndex].Entity;
    13.                 Entity b = physicsWorld.Bodies[ev.BodyIndices.BodyBIndex].Entity;
    14.                 Debug.Log($"collision event: {ev}. Entities: {a}, {b}");
    15.             }
    16.         }
    17.  
    18.  
    19.         BuildPhysicsWorld buildPhysicsWorldSystem;
    20.         StepPhysicsWorld stepPhysicsWorld;
    21.         EndFramePhysicsSystem endFramePhysicsSystem;
    22.  
    23.         protected override void OnCreate()
    24.         {
    25.             buildPhysicsWorldSystem = World.GetOrCreateSystem<BuildPhysicsWorld>();
    26.             stepPhysicsWorld = World.GetOrCreateSystem<StepPhysicsWorld>();
    27.         }
    28.        
    29.         protected override JobHandle OnUpdate(JobHandle inputDeps)
    30.         {
    31.             Debug.Log($"collision system running: {Time.time}"); // this runs correctly
    32.  
    33.             inputDeps = JobHandle.CombineDependencies(inputDeps, buildPhysicsWorldSystem.FinalJobHandle);
    34.             inputDeps = JobHandle.CombineDependencies(inputDeps, stepPhysicsWorld.FinalJobHandle);
    35.            
    36.             var physicsWorld = buildPhysicsWorldSystem.PhysicsWorld;
    37.  
    38.             var collisionJob = new CollisionJob
    39.             {
    40.                 physicsWorld = physicsWorld
    41.             };
    42.             JobHandle collisionHandle = collisionJob.Schedule(stepPhysicsWorld.Simulation, ref physicsWorld, inputDeps);
    43.  
    44.             return collisionHandle;
    45.  
    46.         } // OnUpdate
    47.  
    48.     } // System
    I want some way to get pairs of entities from collision events every frame. How can this be done?
     
  2. thelebaron

    thelebaron

    Joined:
    Jun 2, 2013
    Posts:
    277
    Did you enable "Raises Collision Events" under Advanced in the PhysicsShape options?
     
  3. MixGrey

    MixGrey

    Joined:
    Dec 23, 2014
    Posts:
    9
    I have no PhysicsShape objects. Checking the docs, it looks like PhysicsShape is a MonoBehaviour, which I presume is for hybrid ECS. This is pure ECS and the objects have no relation to GameObjects.

    Is there another way to access that setting for pure ECS?
     
  4. thelebaron

    thelebaron

    Joined:
    Jun 2, 2013
    Posts:
    277
    PhysicsShape is a monobehaviour authoring component which gets converted to a pure ecs representation. The examples repo has more examples of its use which I highly suggest taking a look at, as well as a collision event example.
    https://github.com/Unity-Technologies/EntityComponentSystemSamples/tree/master/UnityPhysicsSamples

    If you are creating the colliders from code well at least that script should contain where Raises Collision Events gets turned into an ecs component property
     
  5. schaefsky

    schaefsky

    Joined:
    Aug 11, 2013
    Posts:
    22
    Could you point me to the collision event example?
     
  6. thelebaron

    thelebaron

    Joined:
    Jun 2, 2013
    Posts:
    277
    schaefsky likes this.
  7. MixGrey

    MixGrey

    Joined:
    Dec 23, 2014
    Posts:
    9
    I think I figured it out. When creating the Collider, there's a field for a Unity.Physics.Material which has a field for a Unity.Physics.Material.MaterialFlags, which is an enum. One of the options is EnableCollisionEvents. I'm not sure what the other two are.

    Creating the Collider like this leads to CollisionEvents actually being generated.

    Code (CSharp):
    1. var material = new Unity.Physics.Material
    2.             {
    3.                 CustomTags = Unity.Physics.Material.Default.CustomTags,
    4.                 Flags = Unity.Physics.Material.MaterialFlags.EnableCollisionEvents |
    5.                     Unity.Physics.Material.MaterialFlags.EnableMassFactors |
    6.                     Unity.Physics.Material.MaterialFlags.EnableSurfaceVelocity,
    7.                 Friction = Unity.Physics.Material.Default.Friction,
    8.                 FrictionCombinePolicy = Unity.Physics.Material.Default.FrictionCombinePolicy,
    9.                 Restitution = Unity.Physics.Material.Default.Restitution,
    10.                 RestitutionCombinePolicy = Unity.Physics.Material.Default.RestitutionCombinePolicy,
    11.             };
    12.  
    13.             var boxCollider = Unity.Physics.BoxCollider.Create(
    14.                 new BoxGeometry{
    15.                     Orientation=quaternion.identity,
    16.                     Size=new float3(0.25f,0.25f,0.25f)},
    17.                 CollisionFilter.Default,
    18.                 material
    19.             );
    Then:
    var colliderComponent = new PhysicsCollider { Value = boxCollider };

    EntityManager.AddComponentData<PhysicsCollider>(entity, colliderComponent);

    and so on.

    I haven't tested whether it sees all of the CollisionEvents it should, but at least it sees some, and that's a start.