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

Ways to do a spawner in ECS?

Discussion in 'Entity Component System' started by 769270865, Jun 1, 2018.

  1. 769270865

    769270865

    Joined:
    Feb 10, 2016
    Posts:
    23
    I have been playing around with ECS for about one week now, and this problem has been bugged me for few days, how do you spawn gameObject(Entity?) at runtime? Studied that sample project but still can't get what is going on.

    Can you put an archetype in a component? like
    Code (CSharp):
    1. struct EnemySpawner : IComponentData
    2. {
    3.      public float CoolDownTime;
    4.      public float TimeSinceLastSpawn;
    5.      public EntityArchetype EmemyArchtype;
    6. }
    and have a job system process and instiatiate this?
     
  2. Soaryn

    Soaryn

    Joined:
    Apr 17, 2015
    Posts:
    328
    Potentially; however,

    1 ) I am guessing as I have not tested this.
    2 ) An Archetype wouldnt be settable in the inspector at the moment, so not sure it would be all that useful. (could be wrong)
     
  3. 769270865

    769270865

    Joined:
    Feb 10, 2016
    Posts:
    23
    Going to try this later, I am talking about Pure ECS here
     
  4. Soaryn

    Soaryn

    Joined:
    Apr 17, 2015
    Posts:
    328
    I don't see anything inside the Achetype struct that would break the normal IComponentData contract so it should be what you are looking for :)
     
  5. 5argon

    5argon

    Joined:
    Jun 10, 2013
    Posts:
    1,555
    You can look in SpawnRandomCircleComponent.cs and SpawnRandomCircleSystem.cs in the demo. The idea is you can have `GameObject` in ISharedComponentData, use with SharedComponentDataWrapper to be able to see in the inspector and drag prefab to it, then finally have entity manager instantiate that after using injection to get it. Also attach `GameObjectEntity` along with the wrapper so that the data comes up in [Inject]

    Code (CSharp):
    1.     /// <summary>
    2.     /// Spawn count Entities based on the specified Prefab. Components on the Prefab will be added to the Entities.
    3.     /// The PositionComponent of each Entity will be set to a random position on the circle described by
    4.     /// the PositionComponent associated with this component and the radius.
    5.     /// </summary>
    6.     [Serializable]
    7.     public struct SpawnRandomCircle : ISharedComponentData
    8.     {
    9.         public GameObject prefab;
    10.         public bool spawnLocal;
    11.         public float radius;
    12.         public int count;
    13.     }
    14.  
    15.     public class SpawnRandomCircleComponent : SharedComponentDataWrapper<SpawnRandomCircle> { }
    Code (CSharp):
    1.     public class SpawnRandomCircleSystem : ComponentSystem
    2.     {
    3.         struct Group
    4.         {
    5.             [ReadOnly]
    6.             public SharedComponentDataArray<SpawnRandomCircle> Spawner;
    7.             public ComponentDataArray<Position>                Position;
    8.             public EntityArray                                 Entity;
    9.             public int                                         Length;
    10.         }
    11.  
    12.         [Inject] Group m_Group;
    13.  
    14.  
    15.         protected override void OnUpdate()
    16.         {
    17.             while (m_Group.Length != 0)
    18.             {
    19.                 var spawner = m_Group.Spawner[0];
    20.                 var sourceEntity = m_Group.Entity[0];
    21.                 var center = m_Group.Position[0].Value;
    22.          
    23.                 var entities = new NativeArray<Entity>(spawner.count, Allocator.Temp);
    24.                 EntityManager.Instantiate(spawner.prefab, entities);
    To have a job process instantiating this I think it might not be possible since we cannot access the entity manager in the job and command buffer could not do a queued instantiate. You might use the command buffer to message other system in the main thread to instantiate for you. Also instantiating this way is already way faster even in the main thread (they said)

    This is as pure ECS as it can get looking from their "Pure ECS" demo. Things will be better in the future as they will make an entity object on the scene and not game object with an adaptor to entity as we have now.
     
    Last edited: Jun 1, 2018
    alexandre-fiset and Deleted User like this.
  6. fhernand

    fhernand

    Joined:
    Mar 17, 2016
    Posts:
    4
    I am trying to apply this to spawn a MonoBehaviour GameObject (an Explosion with dissolve shader). In line 24 in the demo example above I instantiate a prefab X with a GameObjectEntity.

    This prefab X has a MonoBehaviour attached (based on hybrid example from getting_started.md):
    Code (CSharp):
    1.  
    2. using Unity.Entities;
    3. using UnityEngine;
    4.  
    5. class myMB : MonoBehaviour
    6. {
    7.     public GameObject prefab;
    8. }
    9.  
    10. class myMBSystem : ComponentSystem
    11. {
    12.     struct Group
    13.     {
    14.         public myMB  myMB;
    15.     }
    16.  
    17.     override protected void OnUpdate()
    18.     {
    19.         foreach (var e in GetEntities<Group>())
    20.         {
    21.             GameObject.Instantiate(e.myMB.prefab, new Vector3(0, 0, 0), Quaternion.identity);
    22.         }
    23.     }
    24. }
    so myMB tries to instantiate its own prefab, where the pure MonoBehaviour with the dissolve shader resides.

    The X prefab Entities get instantiated, but the logic above does not run, do you have an idea what might be missing?
     
  7. alexandre-fiset

    alexandre-fiset

    Joined:
    Mar 19, 2012
    Posts:
    714
    Well wouldn't be a bit more "pure" to not use a prefab for spawning and instead manage an InstancedMesh and other components (but no UnityEngine GameObject) ?

    @769270865 I'd suggest you take a look at Infalliblecode tutorial on Youtube. His firing system for bullets is all done through nearly-pure ECS and jobs. For 5$ you can have access to the source code, but everything is in his videos anyway.

    But if your idea is to spawn things like animated models, rigidbodies, and etc., you're better going the hybrid route as pure ECS isn't there yet.
     
  8. 5argon

    5argon

    Joined:
    Jun 10, 2013
    Posts:
    1,555
    It's been a long time since then, but now we have `Prefab : IComponentData` (built in component in the lib)

    When attached with any entity it stops showing up in injects/component groups unless specifically ask for it. So you know this one is not intended to be used but just for cloning. You can then "keep aside" this entity somewhere. (like as a system's data, or as an Entity field in your other component etc.)

    Then when you EntityManager.Instantiate ( = clone) with any entity that has Prefab it will not clone the Prefab component. The instantiated entity then can be thought of the real thing that show up in injects/component groups.
     
    Mikael-H likes this.
  9. alexandre-fiset

    alexandre-fiset

    Joined:
    Mar 19, 2012
    Posts:
    714
    Oh, that's a really "good to know" kind of thing. Thanks!