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

Finding entities by ComonentData

Discussion in 'Entity Component System' started by andywatts, May 7, 2018.

  1. andywatts

    andywatts

    Joined:
    Sep 19, 2015
    Posts:
    110
    Pre-ECS, I frequently use singletons to maintain a Dict<int, MyObj> of loaded objects.

    When converting this to ECS and making it available in a job, I see three approaches
    1. In job, call ComponentDataFromEntity<MyObj> and loop over entities testing componentdata
    2. In job, inject SharedComponentData and use GetFilter
    3. Replace Dict with NativeHashMap<int, Entity> and pass (readonly) to the job

    Appreciate any feedback on these.
    Jaochim advises against (2) in this post.
    Think I'm missing a trick with SharedComponentData.. Dict in SharedCompData?
     
    Last edited: May 7, 2018
  2. sngdan

    sngdan

    Joined:
    Feb 7, 2014
    Posts:
    1,154
    I think I am missing the point, what do you want to do in the job? What do you want to filter? Could you describe the desired result with an example...
     
  3. pahe

    pahe

    Joined:
    May 10, 2011
    Posts:
    543
    I'm not sure if that would do the trick for you, but I would try to create a ComponentGroup with a
    ComponentArray<Loaded> Component and the EntityArray. If I understand correctly, the would give you all entities which have the Loaded component attached, so you would need to add that component to all your entities, but then you could easily iterate through them.
     
    Last edited: May 7, 2018
  4. sngdan

    sngdan

    Joined:
    Feb 7, 2014
    Posts:
    1,154
    This is why I asked for clarification - I think @andywatts want's something more than a simple tag.
     
  5. andywatts

    andywatts

    Joined:
    Sep 19, 2015
    Posts:
    110
    I want to reference entities by an id, both in mono-land and in ECS jobs.
    This id is assigned by me. I'm pulling from a database.

    The below seems to work.
    It provides Dictionary<int, Entity> in both Mono and ECS using SharedComponentData.

    Code (CSharp):
    1.     // BlocksController(Entity) => Blocks(SharedDataComponent) => Value(attr)
    2.     public void Start(){
    3.         EntityManager entityManager = World.Active.GetOrCreateManager<EntityManager>();
    4.  
    5.         // Dictionary of entities
    6.         Dictionary<int, Entity> dict = new Dictionary<int, Entity>();
    7.  
    8.         // Controller entity
    9.         Entity BlocksController = entityManager.CreateEntity(typeof(MyController));
    10.  
    11.         // Add dictionary to SharedCompData
    12.         Blocks entities = new Blocks{ Value = dict };
    13.  
    14.         // Add sharedCompData to controller
    15.         entityManager.AddSharedComponentData(BlocksController, entities);
    16.  
    17.         // Prepare job
    18.         var job = new Mesher{
    19.             BlocksController = BlocksController
    20.         };
    21.  
    22.  
    23.  
    24.         // Add some entities
    25.         Entity e1 = entityManager.CreateEntity();
    26.         dict[0] = e1;
    27.  
    28.         job.Schedule();
    29.         //job.Complete();
    30.     }



    The sharedComp dictionary is available from jobs.
    Code (CSharp):
    1. struct Mesher : IJob{
    2.     public Entity BlocksController;
    3.  
    4.     public void Execute() {
    5.         EntityManager entityManager = World.Active.GetOrCreateManager<EntityManager>();
    6.         Blocks Blocks = entityManager.GetSharedComponentData<Blocks>(BlocksController);
    7.         Debug.Log(Blocks.Value.Count);
    8.     }
    9.  
    10. }

    ComponentData looks like this.
    Code (CSharp):
    1.  
    2. [System.Serializable]
    3.  
    4. public struct Blocks : ISharedComponentData{
    5.  
    6.     public Dictionary<int, Entity> Value;
    7.  
    8. }
    9.  
     
    Last edited: May 8, 2018
  6. M_R

    M_R

    Joined:
    Apr 15, 2015
    Posts:
    559
    don't access World.Active from inside the job. accessing a static variable throws up all the safety system and will break when Unity implements proper checks to prevent that (they will)

    you can add a ComponentDataArray or ComponentDataFromEntity to the job if you need to access it.
    or you can use IJobProcessComponentData that takes care of everything (and is parallel)

    you can add an id component to each entity:
    Code (CSharp):
    1. public struct DatabaseId : IComponentData { public int value; }
    the global Dictionary should not be accessed from jobs anyway, you can keep it "outside ECS" i.e. in your DB interface layer (you use it for DB -> ECS operations, and you use the DatabaseID component on the entities for your ECS -> DB operations)
     
    andywatts, starikcetin and pahe like this.