Search Unity

Unity Physics ICollisionEventsJob not being executed?

Discussion in 'DOTS Physics' started by Buretto, Sep 27, 2019.

  1. Buretto

    Buretto

    Joined:
    Mar 23, 2015
    Posts:
    42
    Hi again, I'm hoping someone could help me figure out what's going wrong here. So I am trying to read data from an
    ICollisionEventsJob
    , but for some reason it is not adding any collision data to my NativeList. I'm not sure if this is because the
    Execute()
    function is not being called or if it's happening for some other reason. I have objects that are visibly colliding in my scene.


    Code (CSharp):
    1. using System;
    2. using Unity.Collections;
    3. using Unity.Entities;
    4. using Unity.Jobs;
    5. using Unity.Mathematics;
    6. using Unity.Physics.Systems;
    7. using UnityEngine;
    8. using UnityEngine.Assertions;
    9.  
    10. namespace Unity.Physics.Tests
    11. {
    12.  
    13.     [UpdateBefore(typeof(StepPhysicsWorld))]
    14.     public class CollisionSystem : JobComponentSystem
    15.     {
    16.         BuildPhysicsWorld m_BuildPhysicsWorldSystem;
    17.         StepPhysicsWorld m_StepPhysicsWorldSystem;
    18.         NativeList<CollisionDetails> collisionDetails = new NativeList<CollisionDetails>(1, Allocator.Persistent);
    19.  
    20.         protected override void OnCreate()
    21.         {
    22.             m_StepPhysicsWorldSystem = World.GetOrCreateSystem<StepPhysicsWorld>();
    23.             m_BuildPhysicsWorldSystem = World.GetOrCreateSystem<BuildPhysicsWorld>();
    24.         }
    25.  
    26.         public struct CollisionJob : ICollisionEventsJob
    27.         {
    28.             private bool m_Initialized;
    29.  
    30.             [ReadOnly]
    31.             public PhysicsWorld World;
    32.             public NativeList<CollisionDetails> CollisionDetails;
    33.  
    34.             public void Execute(CollisionEvent collisionEvent)
    35.             {
    36.                 if (!m_Initialized)
    37.                 {
    38.                     CollisionDetails.Clear();
    39.                     m_Initialized = true;
    40.                 }
    41.                 Entity entityA = collisionEvent.Entities.EntityA;
    42.                 Entity entityB = collisionEvent.Entities.EntityB;
    43.                 CollisionEvent.Details collisionEventDetails = collisionEvent.CalculateDetails(ref World);
    44.                 CollisionDetails collisionDetails = new CollisionDetails
    45.                 {
    46.                     ImpulseMagnitude = collisionEventDetails.EstimatedImpulse,
    47.                     ImpulseDirection = collisionEvent.Normal,
    48.                     ImpulsePoint = collisionEventDetails.AverageContactPointPosition
    49.                 };
    50.  
    51.                 CollisionDetails.Add(collisionDetails);            
    52.             }
    53.         }
    54.  
    55.         protected override JobHandle OnUpdate(JobHandle inputDeps)
    56.         {
    57.             m_BuildPhysicsWorldSystem.FinalJobHandle.Complete();
    58.  
    59.             SimulationCallbacks.Callback testCollisionEventCallback = (ref ISimulation simulation, ref PhysicsWorld world, JobHandle inDeps) =>
    60.             {
    61.                 var job =  new CollisionJob
    62.                 {
    63.                     World = m_BuildPhysicsWorldSystem.PhysicsWorld,
    64.                     CollisionDetails = collisionDetails,
    65.                 }.Schedule(simulation, ref world, inDeps);
    66.  
    67.                 job.Complete();
    68.  
    69.                 foreach (CollisionDetails details in collisionDetails)
    70.                 {
    71.                     Debug.Log(details.ImpulseMagnitude);
    72.                 }
    73.  
    74.                 return job;
    75.             };
    76.             m_StepPhysicsWorldSystem.EnqueueCallback(SimulationCallbacks.Phase.PostSolveJacobians, testCollisionEventCallback, inputDeps);
    77.  
    78.             return inputDeps;
    79.         }
    80.  
    81.         protected override void OnDestroy()
    82.         {
    83.             collisionDetails.Dispose();
    84.         }
    85.         public struct CollisionDetails
    86.         {
    87.             public float ImpulseMagnitude;
    88.             public float3 ImpulseDirection;
    89.             public float3 ImpulsePoint;
    90.         }
    91.     }
    92. }
    93.  
     
  2. TRS6123

    TRS6123

    Joined:
    May 16, 2015
    Posts:
    180
    If you're using PhysicsShape, expand the Advanced foldout and make sure "Raises Collision Events" is enabled.
     
    steveeHavok and Buretto like this.
  3. Buretto

    Buretto

    Joined:
    Mar 23, 2015
    Posts:
    42
    Oh my goodness I never thought the solution would be so simple. Thanks very much!
     
  4. stefan-falk

    stefan-falk

    Joined:
    Nov 24, 2019
    Posts:
    15
    Is there actually a way to update components on the colliding entities?

    Something like this:

    Code (CSharp):
    1.  
    2. [BurstCompile]
    3. struct CollisionEventSystemJob : ICollisionEventsJob
    4. {
    5.     public ComponentDataFromEntity<Speed> SpeedComponentData;
    6.     public void Execute(CollisionEvent collisionEvent)
    7.     {
    8.         var entityA = collisionEvent.Entities.EntityA;
    9.         var entityB = collisionEvent.Entities.EntityB;
    10.  
    11.         if (SpeedComponentData.Exists(entityA) && SpeedComponentData.Exists(entityB))
    12.         {
    13.             Debug.Log("Setting Speed.");
    14.             Speed speed = SpeedComponentData[entityA];
    15.             speed.Value = 100;
    16.         }
    17.     }
    18. }
    19.  
    Which is not working unfortunately.
     
  5. steveeHavok

    steveeHavok

    Joined:
    Mar 19, 2019
    Posts:
    427
    Rather than just setting speed.Value = 100, don't you also need to then set SpeedComponentData[entityA] = speed.
     
    stefan-falk and florianhanke like this.
  6. stefan-falk

    stefan-falk

    Joined:
    Nov 24, 2019
    Posts:
    15
    Yes, indeed! That was the problem. I thought that
    SpeedComponentData[entityA]
    is an actual reference to the component and that setting the value will affect it.

    Turns out I was wrong about that. :)
     
  7. elcionap

    elcionap

    Joined:
    Jan 11, 2016
    Posts:
    133
    Components are (mostly) structs, so there is no reference here if it's not explicit (ref/pointer).

    []'s
     
    stefan-falk likes this.
  8. Micz84

    Micz84

    Joined:
    Jul 21, 2012
    Posts:
    345
    I have similar issue I have system with ICollisonEventsJob and ITriggerEventsJob. None of them gets called.
    I have set Collision Response to collide Raise Collision Event. Something ale I am missing? Is there any visual debugger for DOTS physics?

    Code (CSharp):
    1.  
    2. using Components;
    3. using Unity.Entities;
    4. using Unity.Jobs;
    5. using Unity.Physics;
    6. using Unity.Physics.Systems;
    7.  
    8. namespace Systems
    9. {
    10.     [UpdateAfter(typeof(EndFramePhysicsSystem))]
    11.     public class CollisionSystem : SystemBase
    12.     {
    13.         private BuildPhysicsWorld _PhysicsWorld;
    14.         private ISimulation _Simulation;
    15.  
    16.         protected override void OnCreate()
    17.         {
    18.             base.OnCreate();
    19.             _PhysicsWorld = World.GetOrCreateSystem<BuildPhysicsWorld>();;
    20.             _Simulation = World.GetOrCreateSystem<StepPhysicsWorld>().Simulation;
    21.  
    22.         }
    23.  
    24.         protected override void OnUpdate()
    25.         {
    26.             Entities.ForEach((DynamicBuffer<CollisionBuffer> collisionBuffer) => collisionBuffer.Clear()).Run();
    27.             Entities.ForEach((DynamicBuffer<TriggerBuffer> collisionBuffer) => collisionBuffer.Clear()).Run();
    28.  
    29.             var collisionJob = new CollisionJob
    30.             {
    31.                 Collisions = GetBufferFromEntity<CollisionBuffer>()
    32.             };
    33.             var triggerJob = new TriggerJob
    34.             {
    35.                 Collisions = GetBufferFromEntity<TriggerBuffer>()
    36.             };
    37.             var collisionHandle = collisionJob.Schedule(_Simulation, ref _PhysicsWorld.PhysicsWorld, Dependency);
    38.             var triggerHandle = triggerJob.Schedule(_Simulation, ref _PhysicsWorld.PhysicsWorld, Dependency);
    39.             JobHandle.CombineDependencies(collisionHandle,triggerHandle).Complete();
    40.  
    41.         }
    42.  
    43.         private struct CollisionJob : ICollisionEventsJob
    44.         {
    45.             public BufferFromEntity<CollisionBuffer> Collisions;
    46.  
    47.             public void Execute(CollisionEvent collisionEvent)
    48.             {
    49.                 if (Collisions.Exists(collisionEvent.EntityA))
    50.                     Collisions[collisionEvent.EntityA].Add(new CollisionBuffer {Entity = collisionEvent.EntityB});
    51.  
    52.                 if (Collisions.Exists(collisionEvent.EntityB))
    53.                     Collisions[collisionEvent.EntityB].Add(new CollisionBuffer {Entity = collisionEvent.EntityA});
    54.             }
    55.         }
    56.  
    57.         private struct TriggerJob : ITriggerEventsJob
    58.         {
    59.             public BufferFromEntity<TriggerBuffer> Collisions;
    60.  
    61.             public void Execute(TriggerEvent collisionEvent)
    62.             {
    63.                 if (Collisions.Exists(collisionEvent.EntityA))
    64.                     Collisions[collisionEvent.EntityA].Add(new TriggerBuffer {Entity = collisionEvent.EntityB});
    65.  
    66.                 if (Collisions.Exists(collisionEvent.EntityB))
    67.                     Collisions[collisionEvent.EntityB].Add(new TriggerBuffer {Entity = collisionEvent.EntityA});
    68.             }
    69.         }
    70.     }
    71. }
     
  9. petarmHavok

    petarmHavok

    Joined:
    Nov 20, 2018
    Posts:
    454
    Are you seeing collisions between bodies that should raise collision events? At least one of them should have CollideRaiseCollisionEvents. Also for triggers, use RaiseTriggerEvents.

    What you are trying to do looks like something already provided in the samples, DynamicBufferCollisionEventAuthoring and DynamicBufferTriggerEventAuthoring, you might want to take a look at that. In the samples, 2d1. Triggers and 2d2. Collision Events.
     
  10. Micz84

    Micz84

    Joined:
    Jul 21, 2012
    Posts:
    345
    Thanks for a replay, I will look into those samples. I see collisions on of those bodies is a player and other are walls and enemies. Collisions work as they should.
     
  11. Micz84

    Micz84

    Joined:
    Jul 21, 2012
    Posts:
    345
    You are right I am trying to do something similar to code in the samples, not that sophisticated.

    I know why my events did not get triggered. In line 20 I get a ISimulation from StepPhysicsWorld and then I use it in lines 37 and 38. Where I should obtain ISimulation from StepPhysicsWolrd every time I schedule a job. Maybe someone will make the same mistake as I and it will save ones time.
     
    petarmHavok likes this.
unityunity