Search Unity

Component Tags vs Components with booleans

Discussion in 'Entity Component System' started by JakHussain, Feb 19, 2020.

  1. JakHussain

    JakHussain

    Joined:
    Oct 20, 2016
    Posts:
    318
    A typical example shown in many DOTS projects is to create an empty component data type and add it to an entity to differentiate it from other entities that would otherwise have the same archetype without any impact to memory footprint whatsoever. Perfect for many cases.

    However, I'm also aware that adding and removing components from entities invokes a structural change because the entity no longer matches the archetype of other entities in the same chunk so its moved to another chunk with other matching entities or just a new chunk all together.

    I have a set up where I have say a million entities and some property about them is either true or false. The user can edit this property during run time to any random set of these entities, invert the values, set them all true or set them all false. The reason for this feature is because I have a system that is only concerned with entities that DO satisfy this boolean property about them and therefore exclude the entities that don't satisfy the condition.

    If I were to use a component data with an actual boolean inside of it which I set through code, then the system I mentioned earlier would need to loop through all entities and wrap all the job code inside an if which checks this boolean. It also means that my data won't be packed as tightly as possible because I'm loading in data I definitely don't need into the CPU cache.

    However, I also don't want to allow the user to repeatedly make structural changes to the entity memory layout.

    Which is the lesser of these 2 evils in terms of performance? Constantly adding and removing tag components which induce structural changes so my system stays fast or slowing down my system with if statements and loading unnecessary data?

    Is there a third option I haven't thought of?
     
  2. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,761
    This topic comes up every couple of weeks so I'm sure you can find a bunch of in depth discussion and benchmarks on it.

    To answer question quickly though, in a more broad sense, it depends on your application which is better and both are valid strategies.

    My person preference is only change archetype if it'll last a few seconds at the very minimum. If I need to constantly change archetype better to poll.
     
    DotusX, lclemens and Sarkahn like this.
  3. Timboc

    Timboc

    Joined:
    Jun 22, 2015
    Posts:
    238
    I have an annoying use-case - between 1 and 1mil entities, needing updating any duration from every frame and never. Like tertle says, it's very specific to the task but usually polling ends up used a lot. As for myself, I currently just poll but I think I'm planning to move to a hybrid system where a system queues, for example, a max of 10 entities per update to then be tagged. It means managing two things and you still suffer from if's - I don't love it but I mention it because in rare instances I *think* it's a worthwhile approach.
     
  4. 5argon

    5argon

    Joined:
    Jun 10, 2013
    Posts:
    1,555
  5. Sarkahn

    Sarkahn

    Joined:
    Jan 9, 2013
    Posts:
    440
    It feels like this is the big question as a game scales up. Sadly for all the benefits of ECS it seems there's no silver bullet. Tagging entities for processing feels so natural and makes code so readable, it's really unfortunate it comes with such a huge performance consideration.

    I'm currently hitting a bottleneck from this - like @Timboc I have a worst case scenario - potentially hundreds to 1k+ structural changes within a single frame. Switching to polling is going to be a huge headache and based on @5argon 's tests it might not even help since my entities could be diverse with a lot of different components.
     
  6. sngdan

    sngdan

    Joined:
    Feb 7, 2014
    Posts:
    1,154
    I have been out of the loop for a while, but could you not use chunkcomponentdata (or so) to “dirty chunks”, if a real write happens. This way when you loop through later you can skip chunks