Search Unity

Question Build a NativeContainer in one system, then pass it to another?

Discussion in 'Entity Component System' started by Recatek, Mar 28, 2021.

  1. Recatek

    Recatek

    Joined:
    May 2, 2020
    Posts:
    30
    This is a common pattern I'm running into and don't really have a good solution for. I'd like a burst-friendly way to build a NativeContainer of some form (maybe a NativeHashMap look up table) in one system, and once that's done, make it available for other systems to read.

    You can make a system not update until a singleton exists with RequireSingleton, so it makes sense to use a singleton entity. However, NativeContainers can't easily be stored on burst-friendly struct components. Dynamic buffers exist but they don't cover every native container type, like hash maps.

    How would you do this? Blob? Unmanaged singleton? Bypass singletons/entities entirely? There's a lot of ways to do this but I'm not sure what the best practice is. All of them seem clunky and full of boilerplate.
     
  2. DreamingImLatios

    DreamingImLatios

    Joined:
    Jun 3, 2017
    Posts:
    4,264
    Are you looking for something cleaner than storing containers in systems and passing dependencies around, or are you looking for a DynamicBuffer equivalent for more complex structures where only one thread can access the container at a time but a job can access many such containers?
     
  3. Recatek

    Recatek

    Joined:
    May 2, 2020
    Posts:
    30
    Right now the structure is read-only once created, so it doesn't need to be a dynamic buffer (though multiple jobs may read it at once). I'm looking for the ECS best practice way of generating a NativeContainer in one system (e.g. crunching assets, making prefab entities, and putting them in a lookup table) and then safely making it available in other systems, where the other systems only update once that data is available, and stop updating if the data is destroyed. Also ideally in a burst-friendly way, so avoiding unmanaged components if possible. It seems like the intended process would be to put it in a blob on a struct component, but that seems very clunky and I'm wondering if there's a better way.
     
    Last edited: Mar 28, 2021
    apkdev likes this.
  4. DreamingImLatios

    DreamingImLatios

    Joined:
    Jun 3, 2017
    Posts:
    4,264
    The system that owns the container can also set or remove a singleton tag component which when present states that the container is available.

    I have a custom solution for this problem where I allow a ComponentSystemGroup to check if a container exists and if not, it doesn't update any of the systems inside of it. The main benefit of my solution is that it avoids the structural change requirement.
     
  5. Recatek

    Recatek

    Joined:
    May 2, 2020
    Posts:
    30
    I wonder how well this would work with destroying/replacing the data structure. Say you have a system that generates procedural world data in OnCreate and makes it available (public static), and destroys it in its system OnDestroy. You may do this multiple times while running if the player starts a new game, returns to the main menu, starts a new game, etc. Would you then create and destroy the empty singleton marker entity in OnCreate and OnDestroy as well? Would that creation and destruction be immediate? You'd have to be careful that other systems don't try to access the wrong data, or disposed data, and that RequireSingletonForUpdate reacts immediately to the construction or destruction of the entity.
     
  6. calabi

    calabi

    Joined:
    Oct 29, 2009
    Posts:
    232
    I'm curious about a way of doing this also. I have a bunch of data in buffers on a lot of entities and have to use Getbuffer to get access to them on another lot of entities, which isn't really optimal when its thousands of entity's. So I was thinking whether you would be able to create the NativeArrays in the systems when and where they are needed(maybe some struct method) or just create them in a single system and keep them there, but then with that method you have wasted data. Duplicated data which is just doing nothing most of the time.
     
  7. DreamingImLatios

    DreamingImLatios

    Joined:
    Jun 3, 2017
    Posts:
    4,264
    This is a real problem. I have a custom solution in my framework that solves this. But consequently I don't have any good suggestion for standard Unity.
     
  8. Recatek

    Recatek

    Joined:
    May 2, 2020
    Posts:
    30
    Yeah it seems like safe destruction and replacement is the complication here, adding to the fact that it's hard to represent system data dependencies well (e.g. don't run this system until this other system has provided the static data necessary for this one first).