Search Unity

How to setup/initialize EntityCommandBuffer for ITriggerEventJob?

Discussion in 'Physics for ECS' started by Conspiracy, Jan 18, 2020.

  1. Conspiracy

    Conspiracy

    Joined:
    Oct 22, 2016
    Posts:
    40
    after 2 hrs of frustrating confusion, a severe headache, and an urge to throw my laptop to the wall, I've completely given up on trying to learn how to make EntityCommandBuffer work for my trigger job.

    can anyone pls tell me in an easy way how to set up the entityCommandBuffer for ITriggerEventJob?

    I'm trying to make a jobSystem that destroys entities that collides with a trigger collider that I made.

    also if you wanna help dont just give me a wall of text with but structure it with just easy to read points and a straight forward code example. Thank you
     
    imaginadio and alexisbarrette like this.
  2. apaxnid

    apaxnid

    Joined:
    Nov 18, 2012
    Posts:
    35
    Add this to your trigger volume and don't forget to check "Is Trigger"
    Code (CSharp):
    1. [GenerateAuthoringComponent]
    2. public struct TriggerVolume : IComponentData
    3. {
    4.  
    5. }
    And this is basically a copy and paste from Unity's ECS Physics samples which are aviable at https://github.com/Unity-Technologies/EntityComponentSystemSamples
    and the code itself
    Code (CSharp):
    1. using Unity.Burst;
    2. using Unity.Collections;
    3. using Unity.Entities;
    4. using Unity.Jobs;
    5. using Unity.Physics;
    6. using Unity.Physics.Systems;
    7.  
    8. [UpdateAfter(typeof(EndFramePhysicsSystem))]
    9. public class DeleteOnEnterTriggerSystem : JobComponentSystem
    10. {
    11.     EndSimulationEntityCommandBufferSystem m_EntityCommandBufferSystem;
    12.  
    13.     BuildPhysicsWorld m_BuildPhysicsWorldSystem;
    14.     StepPhysicsWorld m_StepPhysicsWorldSystem;
    15.  
    16.    [BurstCompile]
    17.     struct ProcessAllTriggerEventsJob : ITriggerEventsJob
    18.     {
    19.         [ReadOnly] public ComponentDataFromEntity<PhysicsVelocity> PhysicsVelocityGroup;
    20.         [ReadOnly] public ComponentDataFromEntity<TriggerVolume> VolumeGroup;
    21.         public EntityCommandBuffer commandBuffer;
    22.         public void Execute(TriggerEvent triggerEvent)
    23.         {
    24.             Entity entityA = triggerEvent.Entities.EntityA;
    25.             Entity entityB = triggerEvent.Entities.EntityB;
    26.  
    27.             bool isBodyATrigger = VolumeGroup.Exists(entityA);
    28.             bool isBodyBTrigger = VolumeGroup.Exists(entityB);
    29.  
    30.             // Ignoring Triggers overlapping other Triggers
    31.             if (isBodyATrigger && isBodyBTrigger)
    32.                 return;
    33.  
    34.             bool isBodyADynamic = PhysicsVelocityGroup.Exists(entityA);
    35.             bool isBodyBDynamic = PhysicsVelocityGroup.Exists(entityB);
    36.  
    37.             // Ignoring overlapping static bodies
    38.             if ((isBodyATrigger && !isBodyBDynamic) ||
    39.                 (isBodyBTrigger && !isBodyADynamic))
    40.                 return;
    41.  
    42.             if(isBodyATrigger && isBodyBDynamic)
    43.             {
    44.                 commandBuffer.DestroyEntity(entityB);
    45.             }
    46.  
    47.             if (isBodyBTrigger && isBodyADynamic)
    48.             {
    49.                 commandBuffer.DestroyEntity(entityA);
    50.             }
    51.         }
    52.     }
    53.  
    54.     protected override void OnCreate()
    55.     {
    56.         base.OnCreate();
    57.         m_EntityCommandBufferSystem = World.GetOrCreateSystem<EndSimulationEntityCommandBufferSystem>();
    58.         m_BuildPhysicsWorldSystem = World.GetOrCreateSystem<BuildPhysicsWorld>();
    59.         m_StepPhysicsWorldSystem = World.GetOrCreateSystem<StepPhysicsWorld>();
    60.  
    61.     }
    62.     protected override JobHandle OnUpdate(JobHandle inputDependencies)
    63.     {
    64.         var job = new ProcessAllTriggerEventsJob
    65.         {
    66.             PhysicsVelocityGroup = GetComponentDataFromEntity<PhysicsVelocity>(true),
    67.             VolumeGroup = GetComponentDataFromEntity<TriggerVolume>(true),
    68.             commandBuffer = m_EntityCommandBufferSystem.CreateCommandBuffer()
    69.         }.Schedule(m_StepPhysicsWorldSystem.Simulation, ref m_BuildPhysicsWorldSystem.PhysicsWorld, inputDependencies);
    70.  
    71.         m_EntityCommandBufferSystem.AddJobHandleForProducer(job);
    72.         return job;
    73.     }
    74. }
     
    KAV2008 likes this.
  3. WAYNGames

    WAYNGames

    Joined:
    Mar 16, 2019
    Posts:
    992
    The folowing system will add a component to the coliding entities. An other system is then in charge of destroying the entire entity heirarchy (the entities that have the component and recursivly all it's childs). you could just set diretcly the enities to be destroyed in this job if you don't care about the childs

    Code (CSharp):
    1. using Unity.Burst;
    2. using Unity.Collections;
    3. using Unity.Entities;
    4. using Unity.Jobs;
    5. using Unity.Physics;
    6. using Unity.Physics.Systems;
    7.  
    8. [UpdateAfter(typeof(EndFramePhysicsSystem))]
    9. public class CollisionTrigerHierarchyDestructionSystem : JobComponentSystem
    10. {
    11.  
    12.  
    13.     BuildPhysicsWorld buildPhysicsWorldSystem;
    14.     StepPhysicsWorld stepPhysicsWorld;
    15.     EndSimulationEntityCommandBufferSystem m_EntityCommandBufferSystem;
    16.  
    17.     protected override void OnCreate()
    18.     {
    19.         buildPhysicsWorldSystem = World.GetOrCreateSystem<BuildPhysicsWorld>();
    20.         stepPhysicsWorld = World.GetOrCreateSystem<StepPhysicsWorld>();
    21.         m_EntityCommandBufferSystem = World.GetOrCreateSystem<EndSimulationEntityCommandBufferSystem>();
    22.     }
    23.  
    24.     [BurstCompile]
    25.     struct CollisionEventSystemJob : ITriggerEventsJob
    26.     {
    27.         public EntityCommandBuffer EntityCommandBuffer;
    28.         public void Execute(TriggerEvent triggerEvent)
    29.         {
    30.             EntityCommandBuffer.AddComponent(triggerEvent.Entities.EntityA, new DestroyHierarchy());
    31.             EntityCommandBuffer.AddComponent(triggerEvent.Entities.EntityB, new DestroyHierarchy());
    32.         }
    33.  
    34.      
    35.     }
    36.  
    37.  
    38.  
    39.     protected override JobHandle OnUpdate(JobHandle inputDependencies)
    40.     {
    41.         var job = new CollisionEventSystemJob() {
    42.            EntityCommandBuffer =  m_EntityCommandBufferSystem.CreateCommandBuffer()
    43.         }.Schedule(stepPhysicsWorld.Simulation, ref buildPhysicsWorldSystem.PhysicsWorld,
    44.              inputDependencies);
    45.  
    46.         m_EntityCommandBufferSystem.AddJobHandleForProducer(job);
    47.         return job;
    48.     }
    49.  
    50.  
    51. }
    Keep in mind that destroying entities may cause error if they are still referenced by other entities.

    Bonus, the DestroyHierarchy system :
    Code (CSharp):
    1. using Unity.Burst;
    2. using Unity.Collections;
    3. using Unity.Entities;
    4. using Unity.Jobs;
    5. using Unity.Transforms;
    6.  
    7. [UpdateAfter(typeof(CollisionTrigerHierarchyDestructionSystem))]
    8. public class DestroyHierarchySystem : JobComponentSystem
    9. {
    10.     private EntityQuery m_ChildRootGroup;
    11.     private EntityQuery m_RootsGroup;
    12.     private EntityQueryMask m_LocalToWorldWriteGroupMask;
    13.     private EndSimulationEntityCommandBufferSystem m_EntityCommandBufferSystem;
    14.  
    15.     protected override void OnCreate()
    16.     {
    17.         m_EntityCommandBufferSystem = World.GetOrCreateSystem<EndSimulationEntityCommandBufferSystem>();
    18.         m_ChildRootGroup = GetEntityQuery(new EntityQueryDesc
    19.         {
    20.             All = new ComponentType[]
    21.             {
    22.                     ComponentType.ReadOnly<DestroyHierarchy>(),
    23.                     ComponentType.ReadOnly<Child>()
    24.             }
    25.         });
    26.  
    27.         m_RootsGroup = GetEntityQuery(new EntityQueryDesc
    28.         {
    29.             All = new ComponentType[]
    30.             {  
    31.                     ComponentType.ReadOnly<DestroyHierarchy>()
    32.             }
    33.         });
    34.  
    35.     }
    36.  
    37.     [BurstCompile]
    38.     struct DestroyChilds : IJobChunk
    39.     {
    40.         [ReadOnly] public ArchetypeChunkBufferType<Child> ChildType;
    41.         [ReadOnly] public BufferFromEntity<Child> ChildFromEntity;
    42.         public EntityCommandBuffer.Concurrent EntityCommandBuffer;
    43.  
    44.         public void Execute(ArchetypeChunk chunk, int index, int entityOffset)
    45.         {
    46.             var chunkChildren = chunk.GetBufferAccessor(ChildType);
    47.             for (int i = 0; i < chunk.Count; i++)
    48.             {
    49.                 var children = chunkChildren[i];
    50.                 for (int j = 0; j < children.Length; j++)
    51.                 {
    52.                     RecursiveChildsDestroy(children[j].Value,index);
    53.                 }
    54.             }
    55.         }
    56.  
    57.  
    58.         void RecursiveChildsDestroy(Entity entity, int index)
    59.         {
    60.             EntityCommandBuffer.DestroyEntity(index,entity);
    61.             if (ChildFromEntity.Exists(entity))
    62.             {
    63.                 var children = ChildFromEntity[entity];
    64.                 for (int i = 0; i < children.Length; i++)
    65.                 {
    66.                     RecursiveChildsDestroy(children[i].Value, index);
    67.                 }
    68.             }
    69.         }
    70.     }
    71.  
    72.     [BurstCompile]
    73.     struct DestroyHierarchyRootJob : IJobForEachWithEntity<DestroyHierarchy>
    74.     {
    75.         public EntityCommandBuffer.Concurrent EntityCommandBuffer;
    76.  
    77.         public void Execute(Entity entity, int index, [ReadOnly] ref DestroyHierarchy c0)
    78.         {
    79.             EntityCommandBuffer.DestroyEntity(index,entity);
    80.         }
    81.     }
    82.  
    83.     protected override JobHandle OnUpdate(JobHandle inputDeps)
    84.     {
    85.         var childType = GetArchetypeChunkBufferType<Child>(true);
    86.         var childFromEntity = GetBufferFromEntity<Child>(true);
    87.  
    88.         var destroyChilds = new DestroyChilds
    89.         {
    90.             ChildType = childType,
    91.             ChildFromEntity = childFromEntity,
    92.             EntityCommandBuffer = m_EntityCommandBufferSystem.CreateCommandBuffer().ToConcurrent()
    93.         };
    94.         var destroyChildsJobHandle = destroyChilds.Schedule(m_ChildRootGroup, inputDeps);
    95.  
    96.         m_EntityCommandBufferSystem.AddJobHandleForProducer(destroyChildsJobHandle);
    97.  
    98.         var destroyHierarchyRootJob = new DestroyHierarchyRootJob()
    99.         {
    100.             EntityCommandBuffer = m_EntityCommandBufferSystem.CreateCommandBuffer().ToConcurrent()
    101.         };
    102.         var destroyHierarchyRootJobHandle = destroyHierarchyRootJob.Schedule(m_RootsGroup, destroyChildsJobHandle);
    103.  
    104.         m_EntityCommandBufferSystem.AddJobHandleForProducer(destroyHierarchyRootJobHandle);
    105.  
    106.         return destroyHierarchyRootJobHandle;
    107.     }
    108. }
     
    KAV2008 likes this.
  4. Conspiracy

    Conspiracy

    Joined:
    Oct 22, 2016
    Posts:
    40
    Thank you
    you said that destroying an entity whilst it still being referenced may cause an error. How do I deal with that?(like how to un-reference an entity in both monoBehaviour and componentSystem) cause besides causing an error it also makes the game and editor crash.
     
    Last edited: Jan 20, 2020
  5. WAYNGames

    WAYNGames

    Joined:
    Mar 16, 2019
    Posts:
    992
    I have not dealt with tha issue yet.
    My thougth would be to make a system fore each IComponent data that references an entity and when the entity does not exist anymore, set it or destroy it has you need/wish.
     
  6. Conspiracy

    Conspiracy

    Joined:
    Oct 22, 2016
    Posts:
    40
    seems like such a basic issue yet I literally only see one thread on it and there wasnt even a reply on that thread.
     
    shirandror likes this.