Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

[SOLVED] Construct a Job For This CollisionEvent System

Discussion in 'Entity Component System' started by ippdev, Feb 12, 2020.

  1. ippdev

    ippdev

    Joined:
    Feb 7, 2010
    Posts:
    3,850
    Having a tough time constructing a Job for this. The idea is There is one GyroCycle and 0-1000s of atomicSpecies entities. When a collision is detected between the two with the requisite component types I add a component using the EntityCommandBuffer SpeciesCollisionBuffer to each of the collided with species that will allow me to destroy it it in another job after I harvest the contactPoint data in a monobehaviour FixedUpdate () for setting a particle effect before disposing of the entity. I have been round and round trying to figure out how to set this job up as I am not sure what my inputDeps are for this. As well I believe I am supposed to PlayBack the SpeciesCollisionBuffer which I used to Add the component. Again the syntax eluded me there. I am getting there. Once I get the pattern here I should be good to knock out another few subsystems. I am doing this inside a JobComponentSystem. If someone has a better interface to use or alternative method, let's see it, but I would still like to figure this jobs struct, execute, buffers, input deps and final Schedule and returns. I also threw a NativeList in there to store the collided species as CollectedSpecies. Where can I use that? I tried to get everything and the kitchen sink in there!

    Code (CSharp):
    1. [BurstCompile]
    2.     public struct GyroCycleToSpeciesCollision : ICollisionEventsJob {
    3.         [ReadOnly] public PhysicsWorld World;
    4.  
    5.         [ReadOnly] public CollisionWorld collisionWorld;
    6.         //Lookup to get the GyroCycleProxy tagged from a collision
    7.         [ReadOnly] public ComponentDataFromEntity<GyroCycleProxy> gyroCycleProxy;
    8.         //Lookup to get species data from a collision
    9.         [ReadOnly] public ComponentDataFromEntity<AtomicSpeciesData> atomicSpeciesGroup;
    10.         //buffer which will execute all add/remove/instanciate/destroy code
    11.         public EntityCommandBuffer SpeciesCollisionBuffer;
    12.  
    13.         public NativeList<Entity> CollectedSpecies;
    14.  
    15.         public void Execute (CollisionEvent collisionEvent) {
    16.             float3 contactPoint = collisionEvent.CalculateDetails (ref World).AverageContactPointPosition;
    17.             float3 contactNormal = collisionEvent.Normal;
    18.             //getting entityA and B to deduce their membership
    19.             Entity entityA = collisionEvent.Entities.EntityA;
    20.             Entity entityB = collisionEvent.Entities.EntityB;
    21.             //checks to see if entityA and B are GyroCycleProxy
    22.             bool aIsGyroProxy = gyroCycleProxy.Exists (entityA);
    23.             bool bIsGyroProxy = gyroCycleProxy.Exists (entityB);
    24.             //checks to see if entityA and B are Atomic Species
    25.             bool aIsAtomicSpecies = atomicSpeciesGroup.Exists (entityA);
    26.             bool bIsAtomicSpecies = atomicSpeciesGroup.Exists (entityB);
    27.             if (aIsGyroProxy && bIsAtomicSpecies) {
    28.                 SpeciesCollisionBuffer.AddComponent (entityB, new SpeciesToVehicleCollisionTag { });
    29.                 SpeciesCollisionBuffer.SetComponent (entityB, new SpeciesToVehicleCollisionTag {
    30.                     species = atomicSpeciesGroup[entityB].atomicSpecies,
    31.                     contactPoint = contactPoint
    32.                 });
    33.                 CollectedSpecies.Add (entityB);
    34.             } else if (bIsGyroProxy && aIsAtomicSpecies) {
    35.                 SpeciesCollisionBuffer.AddComponent (entityA, new SpeciesToVehicleCollisionTag { });
    36.                 SpeciesCollisionBuffer.SetComponent (entityA, new SpeciesToVehicleCollisionTag {
    37.                     species = atomicSpeciesGroup[entityB].atomicSpecies,
    38.                     contactPoint = contactPoint
    39.                 });
    40.                 CollectedSpecies.Add (entityA);
    41.             }
    42.         }
    43.     }
     
    Last edited: Feb 12, 2020
  2. DreamingImLatios

    DreamingImLatios

    Joined:
    Jun 3, 2017
    Posts:
    4,223
    ITriggerEventsJob runs single-threaded, so it may be easier (and more performant) for you to create a custom struct containing the entity and the contactPoint and then adding that to a NativeList to be used later.

    Granted, if you are only expecting a couple of collisions every couple of frames, it is a lot easier to use an existing EntityCommandBufferSystem rather try to create and manage an EntityCommandBuffer yourself. Since your logic is happening I presume in the SimulationSystemGroup and you are capturing the events in FixedUpdate, I would use BeginInitializationEntityCommandBufferSystem for this. You can get the system using World.GetExistingSystem(), then use CreateCommandBuffer to get the ECB, and finally after you schedule the job you pass the returned JobHandle into AddJobHandleForProducer().
     
  3. ippdev

    ippdev

    Joined:
    Feb 7, 2010
    Posts:
    3,850
    Thanks for your help previously and with this. It has gotten me over a few humps in understanding this after 10 years doing it the other Unity way. This is what I came up with but the syntax of what goes in the job struct and what goes in the OnUpdate with the Schedule(this, inputDeps) eludes me (I get red lines under 'this' no matter what. Basically I loaded up the ECB in the Execute struct. I tried TriggerEvent but could not get a contact point out of intellisense so I am sticking with collisions as that is critical. So now the ECB is loaded up with stuff to do I want it to do it in the OnUpdate Job. Here is the code

    Code (CSharp):
    1. using UnityEngine;
    2. using Unity.Entities;
    3. using Unity.Jobs;
    4. using Unity.Physics;
    5. using Unity.Physics.Systems;
    6. using Unity.Collections;
    7. using Unity.Mathematics;
    8. using Unity.Burst;
    9.  
    10.  
    11. public class GyroCycleToSpeciesCollisionSystem : JobComponentSystem {
    12.  
    13.     private BeginInitializationEntityCommandBufferSystem beginInitBufferSystem;
    14.     private BuildPhysicsWorld physicsWorld;
    15.     private StepPhysicsWorld stepPhysicsWorld;
    16.     private CollisionWorld collisionWorld;
    17.  
    18.  
    19.     protected override void OnCreate () {
    20.         beginInitBufferSystem = World.GetOrCreateSystem<BeginInitializationEntityCommandBufferSystem> ();
    21.         physicsWorld = World.GetOrCreateSystem<BuildPhysicsWorld> ();
    22.         stepPhysicsWorld = World.GetOrCreateSystem<StepPhysicsWorld> ();
    23.     }
    24.  
    25.     protected override JobHandle OnUpdate (JobHandle inputDeps) {
    26.         var jobHandle = new GyroCycleToSpeciesCollision {
    27.             //I have no clue what belongs here..my logic is all complete in the Execute struct
    28.             SpeciesCollisionBuffer = beginInitBufferSystem.CreateCommandBuffer ().ToConcurrent (),
    29.             collisionWorld = collisionWorld,
    30.             //these ^ ^ are here because they are the only damned things didn't get squiggly red lines :)
    31.         }.Schedule(/*what the heck in blue blazes goes here*/);
    32.        
    33.         return jobHandle;
    34.         //how do I run the ECB SpeciesCollisionBuffer from the struct
    35.         //which I think holds the adding and setting of components in the Execute
    36.     }
    37.  
    38.     [BurstCompile]
    39.     public struct GyroCycleToSpeciesCollision : ICollisionEventsJob {
    40.         [ReadOnly] public PhysicsWorld World;
    41.  
    42.         [ReadOnly] public CollisionWorld collisionWorld;
    43.         //Lookup to get the GyroCycleProxy tagged from a collision
    44.         [ReadOnly] public ComponentDataFromEntity<GyroCycleProxy> gyroCycleProxy;
    45.         //Lookup to get species data from a collision
    46.         [ReadOnly] public ComponentDataFromEntity<AtomicSpeciesData> atomicSpeciesGroup;
    47.         //buffer which will execute all add/remove/instanciate/destroy code
    48.         public EntityCommandBuffer.Concurrent SpeciesCollisionBuffer;
    49.  
    50.         public NativeList<Entity> CollectedSpecies;
    51.         int index;
    52.         public void Execute (CollisionEvent collisionEvent) {
    53.             float3 contactPoint = collisionEvent.CalculateDetails (ref World).AverageContactPointPosition;
    54.             float3 contactNormal = collisionEvent.Normal;
    55.             //getting entityA and B to deduce their membership
    56.             Entity entityA = collisionEvent.Entities.EntityA;
    57.             Entity entityB = collisionEvent.Entities.EntityB;
    58.             //checks to see if entityA and B are GyroCycleProxy
    59.             bool aIsGyroProxy = gyroCycleProxy.Exists (entityA);
    60.             bool bIsGyroProxy = gyroCycleProxy.Exists (entityB);
    61.             //checks to see if entityA and B are Atomic Species
    62.             bool aIsAtomicSpecies = atomicSpeciesGroup.Exists (entityA);
    63.             bool bIsAtomicSpecies = atomicSpeciesGroup.Exists (entityB);
    64.             if (aIsGyroProxy && bIsAtomicSpecies) {
    65.                 SpeciesCollisionBuffer.AddComponent (index, entityB, new SpeciesToVehicleCollisionTag { });
    66.                 SpeciesCollisionBuffer.SetComponent (index, entityB, new SpeciesToVehicleCollisionTag {
    67.                     species = atomicSpeciesGroup[entityB].atomicSpecies,
    68.                     contactPoint = contactPoint
    69.                 });
    70.                 CollectedSpecies.Add (entityB);
    71.             } else if (bIsGyroProxy && aIsAtomicSpecies) {
    72.                 SpeciesCollisionBuffer.AddComponent (index, entityA, new SpeciesToVehicleCollisionTag { });
    73.                 SpeciesCollisionBuffer.SetComponent (index, entityA, new SpeciesToVehicleCollisionTag {
    74.                     species = atomicSpeciesGroup[entityB].atomicSpecies,
    75.                     contactPoint = contactPoint
    76.                 });
    77.                 CollectedSpecies.Add (entityA);
    78.             }
    79.             Debug.Log (index+"index");
    80.             index++;
    81.         }
    82.     }
    83. }
    Also, I have that NativeList 'CollectedSpecies' in there. What syntax do I use to access it in FixedUpdate()
     
  4. DreamingImLatios

    DreamingImLatios

    Joined:
    Jun 3, 2017
    Posts:
    4,223
    If a job doesn't get all the data it needs from the Execute arguments, then it needs to get the rest of the data from the member fields, which have to be initialized somewhere. Unity doesn't automatically populate that for you. You have to populate it in OnUpdate and schedule it.

    So ComponentDataFromEntity can be populated using GetComponentDataFromEntity. Also you do not need to make your EntityCommandBuffer concurrent. The non-concurrent one will work fine here and simplifies its usage. Also you need to create your NativeList somewhere using new NativeList<Entity>(Allocator.TempJob) You might replace TempJob with Persistent depending on usage.

    As for how to get the Physics data, I am not the right person to ask. I don't use Unity.Physics personally and am instead rolling my own solution. Unity.Physics has too many weird design restrictions and OOP-isms for my tastes.

    However, part of me thinks you may want to try your hand at some simpler samples to get familiar with DOTS before you try to do complex Physics stuff. A good test I like to challenge people's understanding with is this:
    Calculate and store in a Rank IComponentData the ranking of an entity in order of proximity to the camera. For example, the closest entity to the camera should receive rank 0, the second closest should receive rank 1, and so on.
     
  5. ippdev

    ippdev

    Joined:
    Feb 7, 2010
    Posts:
    3,850
    I am setting and getting data and creating archetypes and changing their values on ttne fly. This collision job is very strict in what you can do which is basically iterate over the collisions. Forget the physics. This is mainly how to make sure that buffer in the struct gets read and does what it was set up to do in the jog..it has something to do with schedule but can't get the damned red lines to disappear. The tech talk whizzed right over this. The docs don't speak directly to it unless I missed it.. I am dizzy with jargon..LOL
     
  6. mattdymott

    mattdymott

    Joined:
    Dec 27, 2016
    Posts:
    29
    Code (CSharp):
    1. var jobHandle = new GyroCycleToSpeciesCollision {
    2.             //I have no clue what belongs here..my logic is all complete in the Execute struct
    3.             SpeciesCollisionBuffer = beginInitBufferSystem.CreateCommandBuffer ().ToConcurrent (),
    4.             collisionWorld = collisionWorld,
    5.             //these ^ ^ are here because they are the only damned things didn't get squiggly red lines :)
    6.         }.Schedule(stepPhysicsWorld.Simulation, ref buildPhysicsWorld.PhysicsWorld, inputDeps);
    For ICollisionEventJobs and ITriggerEventJobs you have to pass in Simulation from StepPhysicsWorld and a ref to the PhysicsWorld from BuildPhysicsWorld
     
    ippdev likes this.
  7. ippdev

    ippdev

    Joined:
    Feb 7, 2010
    Posts:
    3,850
    Thanks @mattdymott as that worked. I had iut sitting in commented out work because it wasn't rolling good with other code I guess. Now I am getting the error

    Code (CSharp):
    1. InvalidOperationException: The NativeContainer GyroCycleToSpeciesCollision.UserJobData.World.CollisionWorld.m_Bodies has not been assigned or constructed. All containers must be valid when scheduling a job.
    I got rid of the NativeList and any native arrays in the ECS code. I use entity queries ToNativeArray in the FixedUpdate and dispose of it but it looks like the Collision World is not created. I saw where someone tried to cache it and Joachim Ante said..you can't cache CollisionWorld, you have to extract it. I think I am doing that with the new keyword..maybe not but it is the only syntax that worked so far. Not sure what he meant by that. That is probably my issue but I have a nice balance in the code with no syntax errors but the console runtime error which if I solve that I should be good to go. I am registering collisions AFAIK.

    Code (CSharp):
    1.  
    2. using UnityEngine;
    3. using Unity.Entities;
    4. using Unity.Jobs;
    5. using Unity.Physics;
    6. using Unity.Physics.Systems;
    7. using Unity.Collections;
    8. using Unity.Mathematics;
    9. using Unity.Burst;
    10.  
    11.  
    12. public class GyroCycleToSpeciesCollisionSystem : JobComponentSystem {
    13.  
    14.     private BeginInitializationEntityCommandBufferSystem beginInitBufferSystem;
    15.     private BuildPhysicsWorld physicsWorld;
    16.     private StepPhysicsWorld stepPhysicsWorld;
    17.     private CollisionWorld collisionWorld;
    18.  
    19.  
    20.     protected override void OnCreate () {
    21.         beginInitBufferSystem = World.GetOrCreateSystem<BeginInitializationEntityCommandBufferSystem> ();
    22.         physicsWorld = World.GetOrCreateSystem<BuildPhysicsWorld> ();
    23.         stepPhysicsWorld = World.GetOrCreateSystem<StepPhysicsWorld> ();
    24.         collisionWorld = new CollisionWorld ();
    25.     }
    26.  
    27.     protected override JobHandle OnUpdate (JobHandle inputDeps) {
    28.         var jobHandle = new GyroCycleToSpeciesCollision {
    29.             SpeciesCollisionBuffer = beginInitBufferSystem.CreateCommandBuffer (),
    30.             collisionWorld = collisionWorld,
    31.         }.Schedule(stepPhysicsWorld.Simulation, ref physicsWorld.PhysicsWorld, inputDeps);
    32.      
    33.         return jobHandle;
    34.     }
    35.  
    36.     [BurstCompile]
    37.     public struct GyroCycleToSpeciesCollision : ICollisionEventsJob {
    38.         [ReadOnly] public PhysicsWorld World;
    39.  
    40.         [ReadOnly] public CollisionWorld collisionWorld;
    41.         //Lookup to get the GyroCycleProxy tagged from a collision
    42.         [ReadOnly] public ComponentDataFromEntity<GyroCycleProxy> gyroCycleProxy;
    43.         //Lookup to get species data from a collision
    44.         [ReadOnly] public ComponentDataFromEntity<AtomicSpeciesData> atomicSpeciesGroup;
    45.         //buffer which will execute all add/remove/instanciate/destroy code
    46.         public EntityCommandBuffer SpeciesCollisionBuffer;
    47.  
    48.  
    49.         public void Execute (CollisionEvent collisionEvent) {
    50.             float3 contactPoint = collisionEvent.CalculateDetails (ref World).AverageContactPointPosition;
    51.             float3 contactNormal = collisionEvent.Normal;
    52.             //getting entityA and B to deduce their membership
    53.             Entity entityA = collisionEvent.Entities.EntityA;
    54.             Entity entityB = collisionEvent.Entities.EntityB;
    55.             //checks to see if entityA and B are GyroCycleProxy
    56.             bool aIsGyroProxy = gyroCycleProxy.Exists (entityA);
    57.             bool bIsGyroProxy = gyroCycleProxy.Exists (entityB);
    58.             //checks to see if entityA and B are Atomic Species
    59.             bool aIsAtomicSpecies = atomicSpeciesGroup.Exists (entityA);
    60.             bool bIsAtomicSpecies = atomicSpeciesGroup.Exists (entityB);
    61.             if (aIsGyroProxy && bIsAtomicSpecies) {
    62.                 SpeciesCollisionBuffer.AddComponent (entityB, new SpeciesToVehicleCollisionTag { });
    63.                 SpeciesCollisionBuffer.SetComponent (entityB, new SpeciesToVehicleCollisionTag {
    64.                     species = atomicSpeciesGroup[entityB].atomicSpecies,
    65.                     contactPoint = contactPoint
    66.                 });
    67.             } else if (bIsGyroProxy && aIsAtomicSpecies) {
    68.                 SpeciesCollisionBuffer.AddComponent (entityA, new SpeciesToVehicleCollisionTag { });
    69.                 SpeciesCollisionBuffer.SetComponent (entityA, new SpeciesToVehicleCollisionTag {
    70.                     species = atomicSpeciesGroup[entityB].atomicSpecies,
    71.                     contactPoint = contactPoint
    72.                 });
    73.             }
    74.         }
    75.     }
    76. }
     
    Last edited: Feb 12, 2020
  8. mattdymott

    mattdymott

    Joined:
    Dec 27, 2016
    Posts:
    29
    I think you need to extract CollisionWorld from PhysicsWorld.CollisionWorld instead of creating it yourself.

    Also think your Job needs to be updated after StepPhysicsWorld.
    Put this above your class:

    [UpdateAfter(typeof(StepPhysicsWorld)), UpdateBefore(typeof(EndFramePhysicsSystem))]
     
    Last edited: Feb 12, 2020
  9. ippdev

    ippdev

    Joined:
    Feb 7, 2010
    Posts:
    3,850
    Added your suggestion as totally appropriate. Tried every method that intellisense allowed but still get the error to get CollisionWorld. Some use a new keyword and others use m_BuildPhyscisWorld.PhysicsWorld.CollisionWorld. But.. It seems to want the m_bodies that are a part of CollisionWorld and I am possibly not sending those to the job. I do not know where I am supposed to get them as most boilerplate code for collisions looks like what I am doing.
     
  10. mattdymott

    mattdymott

    Joined:
    Dec 27, 2016
    Posts:
    29
    The constructor of CollisionWorld takes a 'numBodies' parameter which will then allocate a NativeArray for m_Bodies. This is probably why your getting that error. But not sure you should be constructing it in the first place, I let Unity.Physics do it. I'm not sure where the Physics system gets updated in relation to MonoBehaviours.FixedUpdate. Perhaps its before FixedUpdate and that's why you have a problem.
     
    ippdev likes this.
  11. mattdymott

    mattdymott

    Joined:
    Dec 27, 2016
    Posts:
    29
    Just written and tried a bare bones job to try and understand your problem and I was getting the same error! It didn't work until I put in an EntityQuery for PhysicsVelocity components. Didn't even have to use the query. Had to call inputDeps.Complete() as well even though I haven't had to in previous usages. Very weird.

    Code (CSharp):
    1.  
    2. [UpdateAfter(typeof(EndFramePhysicsSystem))]
    3. public class BareBonesPhysicsEventSystem : JobComponentSystem
    4. {
    5.    private BuildPhysicsWorld BuildPhysicsWorld;
    6.    private StepPhysicsWorld StepPhysicsWorld;
    7.    private EntityQuery VelocityQuery;
    8.  
    9.    protected override void OnCreate()
    10.    {
    11.       BuildPhysicsWorld = World.GetOrCreateSystem<BuildPhysicsWorld>();
    12.       StepPhysicsWorld = World.GetOrCreateSystem<StepPhysicsWorld>();
    13.      
    14.       VelocityQuery = GetEntityQuery(ComponentType.ReadOnly<PhysicsVelocity>());
    15.    }
    16.  
    17.    protected override JobHandle OnUpdate(JobHandle inputDeps)
    18.    {
    19.       inputDeps = new CollisionEventJob
    20.       {
    21.          PhysicsWorld = BuildPhysicsWorld.PhysicsWorld,
    22.          //DynamicGroup = GetComponentDataFromEntity<PhysicsVelocity>(true),
    23.          //CollisionGroup = GetComponentDataFromEntity<CollisionTag>(true)
    24.       }.Schedule(
    25.          StepPhysicsWorld.Simulation, ref BuildPhysicsWorld.PhysicsWorld, inputDeps);
    26.      
    27.       inputDeps.Complete();
    28.  
    29.       return inputDeps;
    30.    }
    31.  
    32.    private struct CollisionEventJob : ICollisionEventsJob
    33.    {
    34.       public PhysicsWorld PhysicsWorld;
    35.  
    36.       //[ReadOnly] public ComponentDataFromEntity<PhysicsVelocity> DynamicGroup;
    37.       //[ReadOnly] public ComponentDataFromEntity<CollisionTag> CollisionGroup;
    38.      
    39.       public void Execute(CollisionEvent collisionEvent)
    40.       {
    41.          var entityA = collisionEvent.Entities.EntityA;
    42.          var entityB = collisionEvent.Entities.EntityB;
    43.  
    44.          //var isDynamicA = DynamicGroup.Exists(entityA);
    45.          //var isDynamicB = DynamicGroup.Exists(entityB);
    46.  
    47.          //var isACollision = CollisionGroup.Exists(entityA);
    48.          //var isBCollision = CollisionGroup.Exists(entityB);
    49.  
    50.          var avgContactPoint = collisionEvent.CalculateDetails(ref PhysicsWorld).AverageContactPointPosition;
    51.          var contactNormal = collisionEvent.Normal;
    52.        
    53.          Debug.Log($"EntityA: {entityA}, EntityB: {entityB}");
    54.          Debug.Log($"ContactPoint: {avgContactPoint}, ContactNormal: {contactNormal}");
    55.       }
    56.    }
    57. }
    58.  
     
    ippdev likes this.
  12. snacktime

    snacktime

    Joined:
    Apr 15, 2013
    Posts:
    3,356
    The collision world and bodies should be obtained from BuildPhysicsWorld every frame in Update like so.

    Code (csharp):
    1.  
    2. var world = BuildPhysicsWorld.PhysicsWorld.CollisionWorld;
    3. var bodies = BuildPhysicsWorld.PhysicsWorld.Bodies;
    4.  
    So no reason to pass both PhysicsWorld and CollisionWorld to a job.

    But that's the easy part. Accessing bodies in a job is tricky to say the least. Because those are being written to by BuildPhysicsWorld which has no clue about jobs you might run that read those bodies, and so it will complain. The solution is rather involved. Enough so if I documented it I'd put it all in a gist not lay it out here. so if you access bodies in a job and get errors about dependencies that's likely the issue.
     
    Thefolle likes this.
  13. ippdev

    ippdev

    Joined:
    Feb 7, 2010
    Posts:
    3,850
    I added the two lines you proposed and they seemed to work. But I still get this error
    Code (CSharp):
    1. InvalidOperationException: The NativeContainer GyroCycleToSpeciesCollision.UserJobData.World.CollisionWorld.m_Bodies has not been assigned or constructed. All containers must be valid when scheduling a job.
    I commented out code in FixedUpdate so I know that is not causing a dependency issue. It seems to come down to the RigidBodyIndex but I can't find much about how to use it and the two or three examples were not suitable and running in ITriggerEventsJob and I need the contacts so I am stuck with ICollisionEventsJob. This is the job as it is with no syntax errors but spits out the above error

    Code (CSharp):
    1.  protected override JobHandle OnUpdate (JobHandle inputDeps) {
    2.         var world = physicsWorld.PhysicsWorld.CollisionWorld;
    3.         var bodies = physicsWorld.PhysicsWorld.Bodies;
    4.         var jobHandle = new GyroCycleToSpeciesCollision {
    5.             SpeciesCollisionBuffer = endSimEntityCommandBufferSystem.CreateCommandBuffer (),
    6.         }.Schedule (stepPhysicsWorld.Simulation, ref physicsWorld.PhysicsWorld, inputDeps);
    7.  
    8.         return jobHandle;
    9.     }
    Then I have this struct which I believe has to have the RigidbodyIndex monkeywrenched (from my POV..LOL) into it. It needs to be in here somehow..No luck on syntax that works yet. Believe me. I ain't sitting awaiting an answer and keep plugging. Here is the Execute code.. UnityTech..this should not be the PIA it is. At least comment your code if yer gonna offer 5000 ways to do something..
    Code (CSharp):
    1.  
    2.     public struct GyroCycleToSpeciesCollision : ICollisionEventsJob {
    3.         [ReadOnly] public PhysicsWorld World;
    4.  
    5.         [ReadOnly] public CollisionWorld collisionWorld;
    6.         //Lookup to get the GyroCycleProxy tagged from a collision
    7.         [ReadOnly] public ComponentDataFromEntity<GyroCycleProxy> gyroCycleProxy;
    8.         //Lookup to get species data from a collision
    9.         [ReadOnly] public ComponentDataFromEntity<AtomicSpeciesData> atomicSpeciesGroup;
    10.         //buffer which will execute all add/remove/instanciate/destroy code
    11.         public EntityCommandBuffer SpeciesCollisionBuffer;
    12.  
    13.         public void Execute (CollisionEvent collisionEvent) {
    14.            //the rigidbodyIndex needs to go in here
    15. //I think it feeds the calcs below
    16.             float3 contactPoint = collisionEvent.CalculateDetails (ref World).AverageContactPointPosition;
    17.             float3 contactNormal = collisionEvent.Normal;
    18.             //getting entityA and B to deduce their membership
    19.             Entity entityA = collisionEvent.Entities.EntityA;
    20.             Entity entityB = collisionEvent.Entities.EntityB;
    21.             //checks to see if entityA and B are GyroCycleProxy
    22.             bool aIsGyroProxy = gyroCycleProxy.Exists (entityA);
    23.             bool bIsGyroProxy = gyroCycleProxy.Exists (entityB);
    24.             //checks to see if entityA and B are Atomic Species
    25.             bool aIsAtomicSpecies = atomicSpeciesGroup.Exists (entityA);
    26.             bool bIsAtomicSpecies = atomicSpeciesGroup.Exists (entityB);
    27.             if (aIsGyroProxy && bIsAtomicSpecies) {
    28.                 SpeciesCollisionBuffer.AddComponent (entityB, new SpeciesToVehicleCollisionTag { });
    29.                 SpeciesCollisionBuffer.SetComponent (entityB, new SpeciesToVehicleCollisionTag {
    30.                     species = atomicSpeciesGroup[entityB].atomicSpecies,
    31.                     contactPoint = contactPoint
    32.                 });
    33.             } else if (bIsGyroProxy && aIsAtomicSpecies) {
    34.                 SpeciesCollisionBuffer.AddComponent (entityA, new SpeciesToVehicleCollisionTag { });
    35.                 SpeciesCollisionBuffer.SetComponent (entityA, new SpeciesToVehicleCollisionTag {
    36.                     species = atomicSpeciesGroup[entityB].atomicSpecies,
    37.                     contactPoint = contactPoint
    38.                 });
    39.             }
    40.         }
    41.     }
     
  14. ippdev

    ippdev

    Joined:
    Feb 7, 2010
    Posts:
    3,850
    It is always some stupid syntax thing. Hopefully they either comment things well or stop with the 900+ line examples we are supposed to mine to do very simple things like..tada..collision detection. I could draw a list up of convoluted syntax we use simply because we have to. I can think of much better names to call methods.. I will try this after a steak dinner to recharge my well depleted brain. I dream in jargon at this point. I am coding turning over and getting the blankets in place!.
     
  15. ippdev

    ippdev

    Joined:
    Feb 7, 2010
    Posts:
    3,850

    It's weird for sure. I have been adding and subtracting lines of code to watch what occurs in the console. I note you are trying to get ComponentDataFromEntity as well and cannot do it and commented it out to get the errors gone. I have tried several Burst compiler modes. One even crashed directly to desktop without any bug report.. I have seen ForEach.With<T> used inside the OnUpdate JobHandle but I cannot even get that to work. I am wondering if this is bugged or what. How else can you possibly get and set component data in the Execute function if they throw errors or crash the application. @MelvMay I have the loop going and getting collisions between A and B but cannot filter nor apply any data to a component.
     
  16. ippdev

    ippdev

    Joined:
    Feb 7, 2010
    Posts:
    3,850
    I just read somewhere the Collision Events in now in Unity.Physics.LowLevel. Not sure if that is why this won't work but I am gonna try another approach than CollisionEvent and ICollisionEventJob until someone can give a good example that is complete of adding and setting component data to components gotten in collision on only entities that have collided and have a specific component.
     
  17. mattdymott

    mattdymott

    Joined:
    Dec 27, 2016
    Posts:
    29
    Those lines do work, I was just commenting stuff out to get it as bare bones as possible.
     
  18. mattdymott

    mattdymott

    Joined:
    Dec 27, 2016
    Posts:
    29
    ippdev likes this.
  19. ippdev

    ippdev

    Joined:
    Feb 7, 2010
    Posts:
    3,850
    Another one of those things I tried in the wrong order, wrong place in the code. Thanks so much for the help with this. May the Gods of your reckoning smile on your day and bring you good fortune! Will give this a go after I get ready for a meeting for a medical sim gig.

    At least folks trying to suss this out have a good example of pitfalls and how it gets done. I searched under every term and there are really about 6 - 10 threads overall with the ICollisionEventsJob stuff happening in them
     
    Last edited: Feb 13, 2020
    mattdymott likes this.
  20. ippdev

    ippdev

    Joined:
    Feb 7, 2010
    Posts:
    3,850
    You should probably add this to make it completed so to speak. I got an error saying I needed to add Complete() ..so the last few lines look like ... Don't want to put SOLVED in the title without that final cue to get it working:) Messed me up a few times. Just found on Collision with proper pair it says EntityCommandBuffer needs to be initialized. Gonna go and do a search. At least I have something I can work thru. Edit..added..now. to get the FixedUpdate culling ParticleSystems and entities based on the added tag

    Code (CSharp):
    1.  protected override JobHandle OnUpdate (JobHandle inputDeps) {
    2.  
    3.         inputDeps = new GyroCycleToSpeciesCollision {
    4.             World = BuildPhysicsWorld.PhysicsWorld,
    5.             atomicSpeciesGroup = GetComponentDataFromEntity<AtomicSpeciesData> (true),
    6.             gyroCycleProxy = GetComponentDataFromEntity<GyroCycleProxy> (true),
    7.             SpeciesCollisionBuffer = endSimEntityCommandBufferSystem.CreateCommandBuffer ()
    8.         }.Schedule (StepPhysicsWorld.Simulation, ref BuildPhysicsWorld.PhysicsWorld, inputDeps);
    9.         endSimEntityCommandBufferSystem.AddJobHandleForProducer (inputDeps);
    10.         inputDeps.Complete ();
    11.         return inputDeps;
    12.     }
     
    Last edited: Feb 13, 2020
  21. mattdymott

    mattdymott

    Joined:
    Dec 27, 2016
    Posts:
    29
    I initially had Complete() in there which was needed before I added the CommandBuffer stuff. I removed it because it worked without it.
    Never had to Initialize the EntityCommandBuffer before, it gets created when the job is scheduled, so not too sure what is going on there.
     
  22. mattdymott

    mattdymott

    Joined:
    Dec 27, 2016
    Posts:
    29
  23. ippdev

    ippdev

    Joined:
    Feb 7, 2010
    Posts:
    3,850
    It is working fine now in ECS land and I emitted 100 atomicSpecies entities right at the gyrocyle, they collided and all picked up the CollidedWithGyroCycle tag and the data made it through. I am currently trying to get the data from CollidedWithGyroCycle into a MonoBehaviour Update, FixedUpdate or LateUpdate loop for setting effects. More wierdities. I have a Debug.Log that should print each loop the number of entites in the query but it doesn't even print at all even though it is in the main loop and not an if conditional. Investigatiung currently. May be because I have all of the scripts classes and job and mono on one big script and dropped it on the GyroCycleProxy..but seems unlikely.. I have seen examples from Unity set up like that..but damned if I can find them right now :)...
    Tada! And..I got it..No big thing.. Moved it over the the ParticlePool GameObject which never traverses into the ECS dimension like the GyroCycleProxy did..but is a bit psychic and with proper open sesame commands the idiot savant ECS responds :) I think I have most patterns I need..and bonus..My framerate using burst is 170-190FPS with 100 rigidbodies and particle systems. Thanks for putting your brain to this Matt.
     
    Last edited: Feb 13, 2020
    mattdymott likes this.