Search Unity

Unity Tech - Where is the SIMPLE Bridge Between MonoBehaviours and ECS??

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

  1. ippdev

    ippdev

    Joined:
    Feb 7, 2010
    Posts:
    3,853
    Hello Unity Tech folks. Why does everything have to be an entity in your examples? Why is their not a very simple method of making a gameObject follow an entity. Don't tell me to restructure my data. It is already atomized and sitting in monobehaviour land. A land it seems forbidden to enter from planet ECS unless you know the correct open sesame secret handshake. I ain't stupid but I ain't a compsci major either. I can get all the data I need from the created entity archetypes to perform a position update to indexed positions that match indexed gameObjects which have..tada! a ParticleSystem attached. Which dies if you convert to an entity or attach it to one. But I can't get that data over to monobehaviour land..or planet ..or universe. I went from making a level every week with all new code and assets to a one month series of crashing to desktop from particles and rigidbodies in monobehaviour and moved over to ECS to see if I could get some physics going. I have that going and am impressed..except..I can't do anything with the entities without trashing everything because of one simple thing which should have been your first thought and not all the tech whiz bang. How the hell can i get a gameObject.transform.position to equal an entity Translation.. I have no problem creating the physics rigidbody entities and attaching and accessing tons of data in ECS land..trying to get a simple array over to a monobehaviour script has been a momentum crushing ordeal to say the least.

    That being said.. Give us some simple way to do this so we can get on to making games and not plough through loads of boilerplate that after all of that reading still has not shown me one concrete method to get the data from a query over to a mono script. All I hear is..you have to restructure your data. No..I don't..that will take months and still won't work as efficiently as it did and my designer, who has been sidelined for a month now can't do a bloody thing. What Unity needs to do is take all that brainpower and make a simple bridging method with a coherent name that does exactly what it should..send a piece of data, an int, a float, a float3, a bool or an array of them specifically to a bool, int, float, or builtin array of a monobehaviour script. Or did I miss something and because everything always skirts the issue of communication between monobehaviour and ECS land.
     
    KenDoolin and davenirline like this.
  2. daschatten

    daschatten

    Joined:
    Jul 16, 2015
    Posts:
    208
    From a MB you have access to World.* with this you can do everything like in "pure" ECS. Get an EntityManager, construct EntityQueries, read and write components...

    Regarding you transform sync issues. There are some components to do this... search for "gameobject" in https://docs.unity3d.com/Packages/com.unity.entities@0.5/api/index.html. Unfortunately there are no Authoring components for them anymore, but you can make them easily yourself.
     
  3. JohnnyTurbo

    JohnnyTurbo

    Joined:
    May 17, 2017
    Posts:
    42
    I recently recreated the Unity Roll-A-Ball tutorial using ECS, and part of that was to have the camera follow the rolling ball.

    My solution to this was to give the CameraFollow script (MonoBehaviour) an Entity variable, which I set to the ball when I spawn the ball in my GameManager script (also a MonoBehaviour). Then in the LateUpdate() I get the Translation data component of the ball using an EntityManager GetComponentData<T>() function. From there I just update the position of the camera based off the Translation component plus an offset.

    Code (CSharp):
    1. using Unity.Entities;
    2. using Unity.Transforms;
    3. using Unity.Mathematics;
    4. using UnityEngine;
    5.  
    6. public class CameraFollow : MonoBehaviour
    7. {
    8.     public Entity ballEntity;
    9.     public float3 offset;
    10.  
    11.     private EntityManager manager;
    12.  
    13.     private void Awake()
    14.     {
    15.         manager = World.DefaultGameObjectInjectionWorld.EntityManager;
    16.     }
    17.  
    18.     private void LateUpdate()
    19.     {
    20.         if (ballEntity == null) { return; }
    21.  
    22.         Translation ballPos = manager.GetComponentData<Translation>(ballEntity);
    23.         transform.position = ballPos.Value + offset;
    24.     }
    25. }
    Here is the point in the video where I demonstrate it if you want to see it in action:



    Hope that helps!
     
  4. thebanjomatic

    thebanjomatic

    Joined:
    Nov 13, 2016
    Posts:
    36
    To test things out I just created a simple MonoBehaviour that spawns old-school prefabs containing a particle system and updates the position to match the corresponding entities translation. Seems to work reasonably well.

    To use, create a game object and add the HybridParticlePool component to it, and then add any number of prefabs for different effect types (smoke, sparks, etc) to the array.

    For each entity that needs an effect add the HybridParticle component and set the prefabIndex to the index of the desired effect.

    Code (CSharp):
    1. public class HybridParticlePool : MonoBehaviour {
    2.     public GameObject[] Prefabs;
    3.     private Dictionary<Entity, Tuple<int, GameObject>> objects;
    4.     private EntityManager manager;
    5.     private EntityQuery query;
    6.  
    7.     void Start() {
    8.         objects = new Dictionary<Entity, Tuple<int, GameObject>>();
    9.         manager = World.DefaultGameObjectInjectionWorld.EntityManager;
    10.         query = manager.CreateEntityQuery(ComponentType.ReadOnly<Translation>(), ComponentType.ReadOnly<HybridParticle>());
    11.         query.SetChangedVersionFilter(typeof(Translation));
    12.     }
    13.  
    14.     private void AddParticleSystem(Entity entity, Translation translation, HybridParticle particle) {
    15.         var obj = Instantiate(Prefabs[particle.prefabIndex], translation.Value, Quaternion.identity);
    16.         objects[entity] = Tuple.Create(particle.prefabIndex, obj);
    17.     }
    18.  
    19.     private void UpdateParticleSystem(Entity entity, Translation translation, HybridParticle particle) {
    20.         if (!objects.ContainsKey(entity)) {
    21.             AddParticleSystem(entity, translation, particle);
    22.         } else {
    23.             var prefabIndex = objects[entity].Item1;
    24.             var obj = objects[entity].Item2;
    25.             if (prefabIndex != particle.prefabIndex) {
    26.                 Destroy(obj);
    27.                 AddParticleSystem(entity, translation, particle);
    28.             }
    29.             obj.transform.position = translation.Value;
    30.         }
    31.     }
    32.  
    33.     private void LateUpdate() {
    34.         var entities = query.ToEntityArray(Allocator.TempJob);
    35.         for (int i = 0; i < entities.Length; i++) {
    36.             var entity = entities[i];
    37.             UpdateParticleSystem(entity, manager.GetComponentData<Translation>(entity), manager.GetComponentData<HybridParticle>(entity));
    38.         }
    39.         entities.Dispose();
    40.     }
    41. }
    42.  
    43.  
    44. [GenerateAuthoringComponent]
    45. public struct HybridParticle : IComponentData
    46. {
    47.     public int prefabIndex;
    48. }
    49.  
     
    Slarti-42, MehO and ippdev like this.
  5. ippdev

    ippdev

    Joined:
    Feb 7, 2010
    Posts:
    3,853
    A real word example. I have a vehicle with a huge hierarchy. It is transferring references to game objects, transforms, UI, arrays of weapons gameObjects who all have more types and references that cannot communicate with ECS and totally fails on conversion to that universe. It can interact with everything except the Unity.Physics, The scene environment has been set up to interact with both Unity.Physics rigidbodies so I have almost everything working and the Unity ECS promise came through on high performance. I can get 5000+ rigidbodies bouncing and colliding at 120fps.

    Now I have two problems that should be very easily solved that has been preventing me from moving forward. I cannot turn the main character Rube Goldberg machine into a entity. It doesn't need to be either. But currently it cannot collide with the Unity.Physics world.Now..the simplest solution is to make a collider shaped like the compound collider in the MonoBehaviour universe, and then simply attach its transform to the main character transform. I can handle the collisions. But again here.. I have like 12 monobehaviour components working in unison. At some point I have to get the collision over to them at some insert point to handle them.. But in my experience so far simply assigning a result from and ECS job or query cannot be shared or sent to a UnityEngine component. Am I missing something?
     
  6. ippdev

    ippdev

    Joined:
    Feb 7, 2010
    Posts:
    3,853
    @JohnnyTurbo @
    I believe it does. It seems I have been listening to the "then assign it to a job" paradigm. This and the one below look more like something I can roll along with. I have certainly been confusing myself by trying to incorporate code examples extending across the life of ECS and alot of advice just sent me down a rabbithole or yer gonna have to restructure yer data. If they had a gander at what I do I have everything atomized, reusable everywhere, accessible from anywhere and a very complex game with over 200 scripts and 50 systems running at 250+ fps. I will test this with my data this evening. Unity need several examples of crosstalking with ECS and standard components in both directions in their next drop. I like the tech demos but they are for if you built your game from scratch..which I now have enough chops in ECS I could do fairly rapidly for smaller games, shooters, pinball and the like. I am trying to simulate actual subatomic physics with the scenario I am creating. The logic is all done and we were making levelsHopefully between yours and the script below I can get back to making games and not studying compsci jargon.
     
    JohnnyTurbo likes this.
  7. thebanjomatic

    thebanjomatic

    Joined:
    Nov 13, 2016
    Posts:
    36
    For what its worth, I was able to do the opposite of my example above by having an ECS system call back into the mono-behavior code without any issues:

    Code (CSharp):
    1. [AlwaysSynchronizeSystem]
    2. [UpdateInGroup(typeof(PresentationSystemGroup))]
    3. public class EcsToGOSystem : JobComponentSystem {
    4.     private HybridParticlePool pool;
    5.     protected override void OnCreate() {
    6.         pool = GameObject.FindObjectOfType<HybridParticlePool>();
    7.     }
    8.     protected override JobHandle OnUpdate(JobHandle inputDeps) {
    9.         Entities
    10.             .WithoutBurst()
    11.             .ForEach((Entity entity, in Translation translation, in HybridParticle particle) => {
    12.                 pool.UpdateParticleSystem(entity, translation, particle);
    13.             }).Run();
    14.         return default;
    15.     }
    16. }
    17.  
    Providing you have a way to get a reference to the game object, and you are running your job code on the main thread and without burst, things should just work.
     
  8. ippdev

    ippdev

    Joined:
    Feb 7, 2010
    Posts:
    3,853
    Thank you sir. My wall and head appreciate the pointers! And the bonus..Not just the code but proper instructions how to use it!! I was about a half hour away from giving up and writing my own ECS particle systems then was thinking..what the hell..no references to sprites or the line renderer..hmm..gotta think about that and get some more reliable patterns..of which i have a few at this point that work great for my headspace. This gameObject transform to entity transform pattern and vice versa seems pretty important for those who have an already made game they are just designing levels for and adjusting gameplay variables.
     
    dannyalgorithmic likes this.
  9. ippdev

    ippdev

    Joined:
    Feb 7, 2010
    Posts:
    3,853
    Yeah.. I reread all that gobbledygook again for the third time in a week right before dinner. Search for yadda yadda and restructure yer data have not been useful to me and have cost me serious money for such a simple thing. This crosstalking should be front and center in their manuals for these systems..not a hidden footnote. Can you point me directly to the data you say I should search for and read? I don't need authoring components. I can author just dandy in ECS for my needs. All my PhysX emitters that crashed after 2019.3f3 can now work again under Unity Havok physics and I can sustain 500 times the number of rigidbodies in Havok than I could in Physx at 120 fps..Just looking for a simple bridge pattern I can put to work and get my designer back in the game before his immense talents wander off out of boredom. The two scripts posted so far in this thread look hopeful for that pattern to emerge in context of my framework. Thanks for yer help and have a great day!
     
  10. ippdev

    ippdev

    Joined:
    Feb 7, 2010
    Posts:
    3,853
    I think a Unity video should be Entities without Jobs..because I think that was the trick effing my head up. The solutions I see here and especially @JohnnyTurbo video both work like I think it should but have not seen these in the examples. U think if someone is converting their game one step at a time the jobs system is gonna screw with them hard. That is why these methods need to be front and center and not some redheaded step child to the cutie pie ECS.
     
    JohnnyTurbo likes this.
  11. ippdev

    ippdev

    Joined:
    Feb 7, 2010
    Posts:
    3,853
    Howdy folks. Just finishing up some touches on the hybrid particle systems to extend it across the whole range of what we expect to use throughout the levels. I figured I would build the pools from scratch and Instantiate at each request, have a total amount to pool of all types and then based on percentage of calls for each type, balance that ratio in the whole pool count ratio. I have a masterPoolIndex that doesn't get reset but a 32 bit into the billions..so I don't think exceeding that will happen. If the entity is nulled in the Dictionary I send back the masterPoolIndex to the particleEFX pool to decide if it needs to be destroyed or repooled based on ratio.

    Heading into CollisionWorld next to solve the one other main issue I need to resolve before returning to making a game at the same pace as prior. I have function everywhere that receive calls from simple collision and trigger scripts. I use a
    Code (CSharp):
    1. public Unity.Event OnCollisionDetected = new UnityEvent();
    2.  
    3. void OnCollisionEnter(Collision collision) {
    4.      OnCollisionDetected.Invoke();
    5. }
    6. }
    The designer can then drop it on a GameObject in the Inspector and drag and drop an object and from the dropdown select the function to call on collision. If I can replicate that but get the collisions from the Unity.Physics world I can hand off the related tasks to the designer to set the levels up and start writing the subatomic attraction and repulsion, magnetic and paramagnetic, half life and crystallograpic interactions. Is there a way to monkeywrench a UnityEvent into an Authoring Component? Or am I not thinking about this correctly? Maybe an Authoring Component and a bridge monobehaviour component with the UnityEvent to that same authoring component that get dropped on the same object, picks up the collision from ECS world and hands it off to the mono component.
     
  12. DreamingImLatios

    DreamingImLatios

    Joined:
    Jun 3, 2017
    Posts:
    4,264
    You can use class IComponentData to do this. It certainly isn't performant, but it is not any slower than forwarding to MonoBehaviours. If you want performance you can represent the event data as an action enum and a target (and maybe an optional float value), as that data can be encoded in NativeContainers and picked up by an event-processing system.
     
    ippdev likes this.
  13. fellowunitydeveloper

    fellowunitydeveloper

    Joined:
    Oct 23, 2019
    Posts:
    7
    here is an example that may give you a better idea on how to link entities with GameObjects in a simple way.

    Code (CSharp):
    1. using Unity.Entities;
    2. using Unity.Jobs;
    3. using Unity.Mathematics;
    4. using Unity.Transforms;
    5. using UnityEngine;
    6.  
    7. // Attach to your Game Object to be converted, the GameObjectPrefab is a pure Game Object with no conversion that may contain MonoBehaviour components such as the particle system.
    8. public class GameObjectPrefabAuthoring : MonoBehaviour, IConvertGameObjectToEntity
    9. {
    10.     public GameObject GameObjectPrefab;
    11.  
    12.     public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem)
    13.     {
    14.         dstManager.AddComponentObject(entity, new GameObjectPrefab
    15.         {
    16.             Value = GameObjectPrefab
    17.         });
    18.     }
    19. }
    20.  
    21. public class GameObjectPrefab : IComponentData
    22. {
    23.     public GameObject Value;
    24. }
    25.  
    26. // Instantiate and destroy the referenced prefab when the entity is created or destroyed. You can even pool the Game Object.
    27. public class GameObjectPrefabSystem : JobComponentSystem
    28. {
    29.     public class GameObjectPrefabInstance : ISystemStateComponentData
    30.     {
    31.         public GameObject Value;
    32.     }
    33.  
    34.     protected override JobHandle OnUpdate(JobHandle inputDeps)
    35.     {
    36.         Entities
    37.             .WithNone<GameObjectPrefabInstance>()
    38.             .ForEach((Entity entity, GameObjectPrefab gameObjectPrefab) =>
    39.             {
    40.                 var gameObjectPrefabInstance = Object.Instantiate(gameObjectPrefab.Value);
    41.  
    42.                 EntityManager.AddComponentData(entity, new GameObjectPrefabInstance
    43.                 {
    44.                     Value = gameObjectPrefabInstance
    45.                 });
    46.  
    47.                 // Just an example to make the GameObject Prefab instance follow the entity.
    48.                 EntityManager.AddComponentObject(entity, gameObjectPrefabInstance.transform);
    49.                 EntityManager.AddComponent<CopyTransformToGameObject>(entity);
    50.             })
    51.             .WithStructuralChanges()
    52.             .Run();
    53.  
    54.         Entities
    55.             .WithNone<GameObjectPrefab>()
    56.             .ForEach((Entity entity, GameObjectPrefabInstance gameObjectPrefabInstance) =>
    57.             {
    58.                 Object.Destroy(gameObjectPrefabInstance.Value);
    59.  
    60.                 EntityManager.RemoveComponent<GameObjectPrefabInstance>(entity);
    61.             })
    62.             .WithStructuralChanges()
    63.             .Run();
    64.  
    65.         return default;
    66.     }
    67. }
    68.  
    69. // A dummy system for testing purposes.
    70. public class DummyEntityWithGameObjectControllerSystem : JobComponentSystem
    71. {
    72.     EntityQuery m_Query;
    73.  
    74.     protected override JobHandle OnUpdate(JobHandle inputDeps)
    75.     {
    76.         var deltaTime = Time.DeltaTime;
    77.         var speed = 3;
    78.         var direction = new float2(Input.GetAxisRaw("Horizontal"), Input.GetAxisRaw("Vertical"));
    79.         var destroy = Input.GetKeyDown(KeyCode.Delete);
    80.  
    81.         if (destroy)
    82.         {
    83.             EntityManager.DestroyEntity(m_Query);
    84.         }
    85.  
    86.         return Entities
    87.             .WithStoreEntityQueryInField(ref m_Query)
    88.             .WithAll<GameObjectPrefab>()
    89.             .ForEach((ref Translation translation) =>
    90.             {
    91.                 translation.Value += math.normalizesafe(new float3(direction, 0).xzy) * speed * deltaTime;
    92.             })
    93.             .Schedule(inputDeps);
    94.     }
    95. }
     
    Slarti-42, BitPax, friflo and 2 others like this.
  14. ippdev

    ippdev

    Joined:
    Feb 7, 2010
    Posts:
    3,853
    I think I am getting the patterns down thanks to the help above so that I can make more complex systems that crosstalk between monobehaviour land and ECS universe. I needed to replace the vehicle to atomicSpecies collision events which destroy the species and add a count to the inventory based on type.

    So my strategy was to add the collision event to the species type tag in a CollisionEvents job system and harvest that ECS data in monobehaviour land to add to the inventory scores. I still need to add the contact point and add a var to the Struct component data along with the collidedWith bool. I also need to figure out how to harvest the contact point in ECS universe. Here is how I am handling a more complex collision query.
    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.  
    8. [UpdateAfter (typeof (BuildPhysicsWorld)), UpdateBefore (typeof (StepPhysicsWorld))]
    9. public class CollisionEventSystem : JobComponentSystem {
    10.     private BuildPhysicsWorld physicsWorld;
    11.  
    12.     private StepPhysicsWorld stepPhysicsWorld;
    13.  
    14.     protected override void OnCreate () {
    15.         this.physicsWorld = World.GetOrCreateSystem<BuildPhysicsWorld> ();
    16.         this.stepPhysicsWorld = World.GetOrCreateSystem<StepPhysicsWorld> ();
    17.     }
    18.  
    19.     protected override JobHandle OnUpdate (JobHandle inputDeps) {
    20.         var handle = new CollisionEventSystemJob {
    21.             SpeciesComponentData = GetComponentDataFromEntity<AtomicSpeciesData> (),
    22.             GyroCycleTagComponent = GetComponentDataFromEntity<GyroCycleTag> ()
    23.         }
    24.             .Schedule (this.stepPhysicsWorld.Simulation, ref this.physicsWorld.PhysicsWorld, inputDeps);
    25.         handle.Complete ();
    26.         return handle;
    27.     }
    28. }
    29.  
    30. struct CollisionEventSystemJob : ICollisionEventsJob {
    31.     public ComponentDataFromEntity<AtomicSpeciesData> SpeciesComponentData;
    32.     //species to add to inventoiry
    33.     public ComponentDataFromEntity<ElectronTag> ElectronData;
    34.     public ComponentDataFromEntity<ProtonTag> ProtonData;
    35.     public ComponentDataFromEntity<NeutronTag> NeutronData;
    36.     private EntityManager em;
    37.  
    38.     public ComponentDataFromEntity<GyroCycleTag> GyroCycleTagComponent;
    39.  
    40.     public void Execute (CollisionEvent collisionEvent) {
    41.         var entityA = collisionEvent.Entities.EntityA;
    42.         var entityB = collisionEvent.Entities.EntityB;
    43.         //Set bools to identify entities
    44.         var bodyAisGyroCycle = GyroCycleTagComponent.Exists (entityA);
    45.         var bodyBisGyroCycle = GyroCycleTagComponent.Exists (entityB);
    46.  
    47.         var bodyAisAtomicSpecies = SpeciesComponentData.Exists (entityA);
    48.         var bodyBisAtomicSpecies = SpeciesComponentData.Exists (entityB);
    49.  
    50.         //find which type of species was collided with
    51.         //set the collidedWithGyroCycle to true to harvest later in monobehaviour land
    52.         if (bodyAisGyroCycle && bodyBisAtomicSpecies) {
    53.             //get the species for A->B
    54.             var species = SpeciesComponentData[entityB];
    55.             var gyroCycle = GyroCycleTagComponent[entityA];
    56.             if (species.atomicSpecies.Equals (AtomicSpeciesData.AtomicParticleSpecies.Proton)) {
    57.                 var protonTag = em.GetComponentData<ProtonTag> (entityB);
    58.                 protonTag.collidedWithGyrocycle = true;
    59.             } else if (species.atomicSpecies.Equals (AtomicSpeciesData.AtomicParticleSpecies.Neutron)) {
    60.                 var neutronTag = em.GetComponentData<NeutronTag> (entityB);
    61.                 neutronTag.collidedWithGyrocycle = true;
    62.             } else if (species.atomicSpecies.Equals (AtomicSpeciesData.AtomicParticleSpecies.Electron)) {
    63.                 var electronTag = em.GetComponentData<ElectronTag> (entityB);
    64.                 electronTag.collidedWithGyrocycle = true;
    65.             } else if (species.atomicSpecies.Equals (AtomicSpeciesData.AtomicParticleSpecies.Positron)) {
    66.                 var positronTag = em.GetComponentData<PositronTag> (entityB);
    67.                 positronTag.collidedWithGyrocycle = true;
    68.             }
    69.         } else if (bodyBisGyroCycle && bodyAisAtomicSpecies) {
    70.             //get the species for B-> A
    71.             var species = SpeciesComponentData[entityA];
    72.             var gyroCycle = GyroCycleTagComponent[entityB];
    73.             if (species.atomicSpecies.Equals (AtomicSpeciesData.AtomicParticleSpecies.Proton)) {
    74.                 var protonTag = em.GetComponentData<ProtonTag> (entityA);
    75.                 protonTag.collidedWithGyrocycle = true;
    76.             } else if (species.atomicSpecies.Equals (AtomicSpeciesData.AtomicParticleSpecies.Neutron)) {
    77.                 var neutronTag = em.GetComponentData<NeutronTag> (entityA);
    78.                 neutronTag.collidedWithGyrocycle = true;
    79.             } else if (species.atomicSpecies.Equals (AtomicSpeciesData.AtomicParticleSpecies.Electron)) {
    80.                 var electronTag = em.GetComponentData<ElectronTag> (entityA);
    81.                 electronTag.collidedWithGyrocycle = true;
    82.             } else if (species.atomicSpecies.Equals (AtomicSpeciesData.AtomicParticleSpecies.Positron)) {
    83.                 var positronTag = em.GetComponentData<PositronTag> (entityA);
    84.                 positronTag.collidedWithGyrocycle = true;
    85.             }
    86.         }
    87.     }
    88. }
    So now I got all the vars set so I can harvest them in mono land below and finally send them to the inventory controller

    Code (CSharp):
    1. public class GyroCycleToSpeciesCollisions : MonoBehaviour {
    2.     public VehicleInventoryController vehicleInventoryController;
    3.     //ECS
    4.     private EntityManager manager;
    5.     private EntityQuery protonSpeciesQuery;
    6.     private EntityQuery neutronSpeciesQuery;
    7.     private EntityQuery electronSpeciesQuery;
    8.     private EntityQuery gyroCycleQuery;
    9.     // Start is called before the first frame update
    10.     void Start () {
    11.         manager = World.DefaultGameObjectInjectionWorld.EntityManager;
    12.         protonSpeciesQuery = manager.CreateEntityQuery (ComponentType.ReadOnly<ProtonTag> ());
    13.         neutronSpeciesQuery = manager.CreateEntityQuery (ComponentType.ReadOnly<NeutronTag> ());
    14.         electronSpeciesQuery = manager.CreateEntityQuery (ComponentType.ReadOnly<ElectronTag> ());
    15.         gyroCycleQuery = manager.CreateEntityQuery (ComponentType.ReadOnly<GyroCycleTag> ());
    16.     }
    17.  
    18.     // Update is called once per frame
    19.     void FixedUpdate () {
    20.     int protonsCollidedWith = 0;
    21.     int neutronsCollidedWith = 0;
    22.     int electronsCollidedWith = 0;
    23.  
    24.         var protonEntities = protonSpeciesQuery.ToEntityArray (Allocator.TempJob);
    25.         for (int i = 0; i < protonEntities.Length; i++) {
    26.             if (manager.GetComponentData<ProtonTag> (protonEntities[i]).collidedWithGyrocycle) {
    27.                 protonsCollidedWith++;
    28.             }
    29.         }
    30.         protonEntities.Dispose ();
    31.  
    32.         var neutronEntities = neutronSpeciesQuery.ToEntityArray (Allocator.TempJob);
    33.         for (int i = 0; i < neutronEntities.Length; i++) {
    34.             if (manager.GetComponentData<NeutronTag> (protonEntities[i]).collidedWithGyrocycle) {
    35.                 neutronsCollidedWith++;
    36.             }
    37.         }
    38.         neutronEntities.Dispose ();
    39.  
    40.         var electronEntities = electronSpeciesQuery.ToEntityArray (Allocator.TempJob);
    41.         for (int i = 0; i < electronEntities.Length; i++) {
    42.             if (manager.GetComponentData<ElectronTag> (electronEntities[i]).collidedWithGyrocycle) {
    43.                 electronsCollidedWith++;
    44.             }
    45.         }
    46.         electronEntities.Dispose ();
    47.  
    48.         vehicleInventoryController.AddAtomicSpeciesToInventory (protonsCollidedWith, neutronsCollidedWith, electronsCollidedWith);
    49.     }
    50. }
    I can keep adding collision types and queries to this now and add damage to the positron tag to send to damage controller and collision efx pool. Gonna work on contacts in the morning. Hope this helps someone. And thanks to the folks above for a good set of reusable patterns I can get a grip on this with.
     
  15. ippdev

    ippdev

    Joined:
    Feb 7, 2010
    Posts:
    3,853

    That's pretty cool. I will make use of it.. It may help begin the conversion of the vehicle to ECS with a few of the code snippets I spot in there.The other half of this that I assume many folks would need the mechanic of is having an ECS rigidbody follow a PhysX rigidbody. For tests I placed an ECS rigibody collider on an empty GameObject as a child of the vehicle hierarchy, tried setting it to both kinematic and dynamic and drove the vehicle around and checked the debugger. It was there, you could see it move around with the vehicle in the Scene view. But the Translate and Rotation components of course did not reflect it's actual position and rotation and the PhysicsVelocity was as close as you can get to zero. It of course collided with nothing. As far as it knew it was still sitting where it was when I hit Play. assume..I will try tomorrow, that I have to set the rigidbody Angular Velocity and LinearVelocity based on the PhysX rigidbody velocity and angular velocity. But since one is stateful and one stateless are they gonna sync up? Anyone got a clue on this?
     
  16. AdamBebko

    AdamBebko

    Joined:
    Apr 8, 2016
    Posts:
    168
    This thread is really helpful. Thanks all.