Search Unity

The bottleneck of Add/Remove component on large numbers of entities

Discussion in 'Entity Component System' started by Greenwar, Jul 16, 2019.

  1. Greenwar

    Greenwar

    Joined:
    Oct 11, 2014
    Posts:
    54
    We all know that it's a bad to add or remove individual components and that you're better off batching as much as possible. But consider the following scenario:
    1. There are 500,000 entities with a Countdown component on them
    2. Each Countdown component has a random value of 1-100f
    3. A IJFEWE subtracts from the value by deltatime
    And finally:
    When the value reaches >= 0f the Countdown component is removed, or the entity is destroyed.

    What's the best practice of handling such a scenario in a performant way? It renders any batching options less than ideal. The chunks will be constantly rebuilt which will eat away at performance.

    If you instantiate them all and just disable them when they reach 0 you run into more problems such as having to resort to PostCommandBuffers and the component will still be there if it's reactivated.

    Are tags the best option here? It's feel unnecessarily rigid having to have every component that the entities will ever use beforehand.
     
  2. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,761
    So I'm not sure I would even attach a countdown component to the entities directly.

    I'd probably create 50000 new entities with a countdown component with an entity field.

    Or maybe not even use entities, just store the countdown info in a container on a system.
     
  3. Singtaa

    Singtaa

    Joined:
    Dec 14, 2010
    Posts:
    492
    Yes, in your example, I believe having a
    Countdown
    component along with a
    CountdownActive
    tag component (zero-sized) will be the most performant way to go about it since you will only need to add/remove the tag component instead of the value component. The down side for more complicated use cases is like you said, there may be memory considerations because all the value components need to be present upfront.

    One thing worth mentioning is that the ECS team (well @Joachim_Ante mostly) has said a few times that they are continuously working on more performance optimizations for tags and ECBs.
     
  4. snacktime

    snacktime

    Joined:
    Apr 15, 2013
    Posts:
    3,356
    The most important information you didn't say, which is what do these entities represent?

    I wouldn't have a countdown per entity paradigm period, I'd just select N entities per frame. Use whatever system works best for storing references to them.

    Let's say this mechanic is the game. it's over when all entities are destroyed. I would create a NativeArray to store the entities I created. I would select a number to destroy each frame, starting at index 0 in the array and tracking the current index. I'd take the range to destroy as a NativeSlice and use that to batch destroy the entities.

    If these entities represent a transform or renderer, then I'd consider that most likely the best real world solution involves some other well known approach to reduce the number of entities.
     
  5. TLRMatthew

    TLRMatthew

    Joined:
    Apr 10, 2019
    Posts:
    65
    You could also just make the job write any entities whose countdown reaches 0 into a NativeQueue.Concurrent, then have a separate job convert the Queue into a NativeList (as Tertle has written about recently), then you're free to use the batch APIs.
     
    gfoot likes this.