Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Adding the same component multiple times on the same entity

Discussion in 'Entity Component System' started by nantoaqui, Jun 26, 2019.

  1. nantoaqui

    nantoaqui

    Joined:
    Oct 1, 2014
    Posts:
    42
    Hello,

    I was wandering how to stack the same component multiple times on the same entity. Currently I don't know how to properly handle this scenarios:

    Code (CSharp):
    1. Damage : IComponentData {
    2.     public int Value;
    3. }
    Different types of enemies adding damage to Player's entity. The approach bellow doesn't feel nice:

    Check if component is already present on the entity, if so, accumulate the new value

    Code (CSharp):
    1. if(DamageComponents.Exists(entity)) {
    2.   var damage = DamageComponents[entity];
    3.   damage.Value =   damage.Value + newDamage;
    4. buffer.SetComponent(index, entity, damage);
    5. }
    The other case would be `WaitForSecondsComponent`. This should act as coroutine, by postpone some operation by an amount of seconds. Once it is complete it should add a `WaitForSecondsCompleteComponent` to the entity.

    This fall one the same example listed above for Damage. What if different systems decides to add `WaitForSecondsComponent` to the same entity?

    Code (CSharp):
    1. [RequireComponentTag(typeof(Spell))
    2. public struct DelayedJob : IJobForEachWithEntity<WaitForSecondsCompleteComponent>
    Code (CSharp):
    1. [RequireComponentTag(typeof(DepleteHealth))
    2. public struct DelayedJob : IJobForEachWithEntity< WaitForSecondsCompleteComponent>
    Thanks a lot!
     
  2. daschatten

    daschatten

    Joined:
    Jul 16, 2015
    Posts:
    208
    More options:

    1. Use a DynamicBuffer (= a List) for hits

    2. Spawn an entity with a damage (entity source, entity target, int damageAmount) component every time damage is taken

    3. Use a persistent Hit (int hitCount, int Damage) component and every time damage is received increase hit count and add damage

    Depends on your needs :)
     
  3. Enzi

    Enzi

    Joined:
    Jan 28, 2013
    Posts:
    954
    What daschatten said, I'd go with spawning entities and a dedicated system to handle it. Cleaner but in more complicated setups, buffers are easier to squeeze in.

    Regarding the WaitForSeconds. Don't make it generic, name the comp so you know for what it waits for, that way you can also design the correct process when other systems are interacting on this.
    For example, you can use WaitForSpell as exclude in a system entity query. That way a system that handles spellcasting doesn't even operate on ones that are already casting. Usually this would be a condition in code but in ECS a query is enough.

    Then the comp just needs an endtime or starttime+waitTime and a system that checks for remaining time, removes the comp when done and adds the complete comp/tag.
     
    nantoaqui likes this.
  4. nantoaqui

    nantoaqui

    Joined:
    Oct 1, 2014
    Posts:
    42
    @daschatten & @Enzi thanks for you answers!

    I guess that i'll make the components in the most declarative way to avoid confusion. eg: WaitForSpell.

    And try to move the common logic to a different module.