Search Unity

Removing/adding components not specified in initial archetype

Discussion in 'Entity Component System' started by tiggus, Jan 26, 2019.

  1. tiggus

    tiggus

    Joined:
    Sep 2, 2010
    Posts:
    1,240
    Quick question on archetypes and efficiency. It is my understanding that archetypes are packed into memory based on their profile(ComponentA, B,C) lets say is ArchetypeA.

    If I sequentially add/remove ComponentD to my list of entities via a TurnSystem is this affecting the performance of ArchetypeA?

    The problem attempting to be solved is designating which entity's turn it is to process in a turn based game.

    The other systems would be something like MovementSystem<ComponentA, ComponentD> so that movement is only processed for the entity whose current turn it is.

    OR

    Would it be better to include ComponentD(TurnComponent) in the initial archetype and simply flip a bool in it to true or false. In this case all the other systems would have to check all the entities to see what the value is.
     
    Last edited: Jan 26, 2019
  2. tiggus

    tiggus

    Joined:
    Sep 2, 2010
    Posts:
    1,240
    On second thought maybe I should just have the TurnSystem manually invoke all of the game systems as it iterates through the list of actors.
     
  3. orionburcham

    orionburcham

    Joined:
    Jan 31, 2010
    Posts:
    488
    This is a perfectly valid way to do it. Actually both approaches you've listed would be valid, they'd just have different performance trade offs. :)

    1. Only the active unit has a "TurnComponent": This is often referred to as 'tagging', and is the approach most commonly talked about on these forums. The benefit is that your systems only have to work on entities with the 'tag' component. The downside is that it adds more archetype fragmentation, which can introduce cache misses.

    2. Everything has a "TurnComponent", which uses a bool: This would be limit archetype fragmentation, but each of your systems would have to iterate over every entity which could have a turn, to check that bool.

    3. A TurnSystem manually invokes other Systems: I'm guessing this is an evolution of #2, in which TurnSystem would iterate over everything with a TurnComponent, and then call out to other systems when it hits the one with a 'true' bool. This pattern sounds like it will fight the established ECS patterns at play here - Unity is hoping you will have a single instance of each System, which run in an order defined by Unity. Unity wants to own this System execution order, since they can do a lot of optimizations involving data dependencies and parallel jobs. They seem to be proceeding with a soft assumption that you'll do things this way, and that assumption may become harder has their API becomes more finalized.

    This approach also goes against the ways Unity expects Systems to be written. There's an expected cadence of "Grab some chunk data -> process that chunk data -> assign that modified data". If you start using Systems more as Utility classes (calling out to them, ad-hoc, at the moment when you need work done), it breaks this general pattern. You may find yourself missing out on some larger ECS optimizations, and fighting Unity's API.

    All that said, however, Either of the first two approaches seem just fine. Knowing which one would be more performant for your project would be difficult before writing all of your systems. You'd need to know how many cache misses #1 would introduce, vs. how much CPU time you'll lose from checking that TurnComponent bool in #2. That really comes down to how many Systems you have, and how they're reading and writing to that data.

    Fwiw, most people on this forum would probably recommend approach #1. It's difficult to predict the impact of cache misses at the beginning of a project, but you can see that the work of checking that TurnComponent bool will grow exponentially with the number of entities, and the number of systems processing them.

    However, it's worth noting that you may not notice any meaningful perf differences from either approach in a turn based game. :)

    It's also worth noting that, although archetype fragmentation is currently an unavoidable side-effect of component tagging, Joachim Ante has said elsewhere that he'd like to specifically look into optimizations there this year. It's at least on their minds.

    Hope some of this was helpful. Good luck!
     
    Last edited: Jan 26, 2019
    tiggus likes this.
  4. tiggus

    tiggus

    Joined:
    Sep 2, 2010
    Posts:
    1,240
    @orionburcham Thanks! it is great that folks are so quick to respond on here and validate these assumptions. To be honest, this is a turn based game so performance is not really an issue but I like to know I am doing things the idiomatic way from the beginning.

    I will go with approach #1(tagging) as it makes a lot of sense to me.
     
    orionburcham likes this.