Search Unity

Adding and Removing Components at run-time

Discussion in 'Entity Component System' started by Cywizz, Jun 27, 2018.

  1. Cywizz

    Cywizz

    Joined:
    Oct 5, 2017
    Posts:
    17
    Hi all,

    I have been playing around for the last few weeks with ECS and thought I had a good understanding of how it all fits together. Well this was until I read up on how memory allocation works.

    How I understand it; The ECS stores each entity and its components (based on its archetype) in a flat structure in memory, packed against each other. This makes it very fast.
    However, the ECS framework ALLOWS you to add and remove components to an entity at run-time, which will result in a re-allocation of that chuck somewhere else, due to its new size. I assume this is not so fast.

    I have a practical example that I am using in a 2d game I am playing around with to understand the concepts:

    - A NPC has hearing and sight attribute components, each holding a value representing the range of each sense. This range can change throughout the game through buffs, etc
    - Once a NPC hears something in range, I add a HearingEvent component with a float2 representing the world location.
    - A system acts on all NPCs with this HearingEvent component and then moves to that location
    - If the NPC sees an enemy, then a SeenEvent gets added and HearingEvent removed. The SeenEvent holds an entity reference to the enemy
    - Another system acts on the NPCs with this SeenEvent and attacks the enemy, etc, etc

    So in this logic I basically add 2 new components to the archetype at run-time and remove at least one.

    Will a better option be to rather have a HearingManager entity, which only has 1 component: HearingEvent which in turn has a reference to the NPC's Entity and move the character from there? How will the performance be looking up the entity from this HearingManager system with all the required components?

    I will really appreciate your views and feedback on this.
     
  2. dartriminis

    dartriminis

    Joined:
    Feb 3, 2017
    Posts:
    157
    Unity has mentioned in the past that components may be used to "tag" entities (as you do with the seen and hearing components).

    I think your implementation is a good start, and unless you see performance issues you shouldn't have a problem. As always, you can try both methods, measure performance differences, and make an informed decision on which implementation is better :)
     
  3. Cywizz

    Cywizz

    Joined:
    Oct 5, 2017
    Posts:
    17
    Thank you for the reply...It is definitely working well so far. I get 2000 npcs all running around, listening, seeing, fighting, screaming for help and even fleeing, based on their attitude toward each other, which is quite amusing to look at This at 40fps through the editor.
    This without doing anything through the job system yet. :cool:.

    I ported the idea from a FSM design I had before and the first thing that strikes me is yes, you have more code/scripts but it is much easier to understand and to reuse. It definitely takes a few iterations to get the thinking right though!

    I will refactor the solution and go with the separate "event" entities and see if it makes a difference to look up bulk entities and components. In the long run it might be beneficial not to add/remove all these components so I will have to investigate. I am also keen to see how Unity will shape the new reactive systems in the near future.

    Cheers
     
    zulfajuniadi likes this.
  4. 5argon

    5argon

    Joined:
    Jun 10, 2013
    Posts:
    1,555
    The empty tag component is "officially" encouraged by [RequireComponentTag(typeof(...))] !

    Code (CSharp):
    1.         [RequireSubtractiveComponent(typeof(EcsTestData3))]
    2.         [RequireComponentTag(typeof(EcsTestData4))]
    3.         struct ProcessTagged : IJobProcessComponentData<EcsTestData, EcsTestData2>
    4.         {
    5.             public void Execute(ref EcsTestData src, ref EcsTestData2 dst)
    6.             {
    7.                 dst.value1 = dst.value0 = src.value;
    8.             }
    9.         }
     
  5. nzhangaudio

    nzhangaudio

    Joined:
    May 26, 2015
    Posts:
    20
    It seems that this only works on jobs, not ComponentGroups in ComponentSystem.