Search Unity

Entities Ordered by Component Value? & Using Components Added Mid-Iteration?

Discussion in 'Entity Component System' started by S_Darkwell, Sep 3, 2019.

  1. S_Darkwell

    S_Darkwell

    Joined:
    Oct 20, 2013
    Posts:
    320
    Hello All!

    I am in the early stages of designing a rogue-like, but am uncertain how to approach the issue below using Unity's DOTs ECS.

    In this rogue-like, characters with a higher Attack.Speed should attack before characters with a lower Attack.Speed.

    For example:
    1. A fast character and a slow character perform a lethal attack on each other
    2. The fast character first kills the slow character
    3. The slow character, having been killed, is not able to attack the fast character

    I'm considering the following:
    1. Instantiate character Entities with Attack components; Attack components contain a Speed value
    2. When attacking, an AttackTarget component is added and its Value is set to the entity being attacked
    3. AttackSystem retrieves all components with both an Attack component and AttackTarget component
    4. Entities are sorted in descending order by their Attack component's Speed value
    5. Entities are iterated through, checking whether or not their AttackTarget character is killed
    6. When an attack successfully kills a character, an IsDead flag component is added to the killed entity
    7. Entities with an IsDead flag component are skipped by the AttackSystem

    My concerns are:
    • Sorting the retrieved entities may not be performant or may result in garbage
    • I'm uncertain how to take the newly-added IsDead components into consideration during the iteration

    As I am unskilled with Unity's Entity-Component-System architecture, any guidance is much appreciated!

    Thank you in advance and be well. :)
    - S.
     
  2. Ashkan_gc

    Ashkan_gc

    Joined:
    Aug 12, 2009
    Posts:
    1,124
    The way that comes to mind is to have two systems.
    System one runs first and finds all entities attacking each other at a turn
    Then a second system compares all related values in entities which are attacking each other and decides who dies.
    another way would be to simply have one system and one iteration but when you are trying to attack another entity with the higher speed value then you skip attacking and let the iteration moves forward so the other attacks you.

    It really much depends on frequency of attack checks, what else needs to be checked? is it real time or turn based ...

    but in general if two entites should be considered for something , you either should do all of the checks when first of them is trying to do something and get the other entity's data using GetComponentData or simply generate a set of pairs in an earlier job system and then execute attacks in another system. since I don't know how your entities find out who they will attack, cannot tell you a good design, give me more info and i'll be able to help more
     
    S_Darkwell likes this.
  3. S_Darkwell

    S_Darkwell

    Joined:
    Oct 20, 2013
    Posts:
    320
    Hello @Ashkan_gc,

    Thank you for taking the time to respond!

    Currently, I am looking at a nearly-empty project and I'm exploring many gameplay possibilities, so concrete specifications are a bit difficult at the moment. I expect interactions and movement will be turn-based, but am uncertain at the moment as to whether player action will advance the turn or they will continuously progress on their own--though at the moment, I'm leaning toward the latter.

    The order-of-attack is actually only one of many actions that must be sorted by speed. Furthering the attack example, characters may also have a dodge ability that has a chance to reduce damage from the incoming attack, but only if their dodge speed is equal to or greater than the incoming attack. Likewise, they may also have a move speed, and if their move speed exceeds the speed of the attack, the attacker will miss (but the moving character may suffer other penalties).

    As I continue to ponder the issue, I'm wondering if it would be more appropriate to have some sort of action queue that is sorted by each action's speed. A system could then sort the action queue, then add components in ascending order, checking for the value/existence of other components as it does so.

    Would that be a performant approach? Also, is there a way to check for the existence of components within the same iteration in which they were added? Or is there another approach that you or others might recommend?

    Thank you again and be well!
    - S.
     
  4. Ashkan_gc

    Ashkan_gc

    Joined:
    Aug 12, 2009
    Posts:
    1,124
    in general sorting using a value every frame is not a good idea but you can put entity references in buckets for each speed if they are int values and the range is like 0-1000

    In general the way that entities find out who they should attack is very important. assuming that in each frame you'll find out who you might attack or not then easiest would be to do something like this
    for each entity check all of the units which it might attack and based on its sped and other's speed and other params, you find out if the attack hits or misses. if you decide how you handle attacks from both then you are done.
    however this means you should access multiple entities from both entities and some components might/might not be on all entities which can attack/be attacked so making it more performant means you need to find out what exactly you want to do.

    Best way is to explore using Entities.Foreach and a sequential single threaded way and when you know more exactly what will run, you'll be able to optimize it.
    ou should decie for example in your gameplay, do you dodge first or attack first in the current frame or you want to calculate both at the same time. for example if you decide to calculate both at the same time then you can have a job component system which takes al entities which have attack and dodge and speed and also have access to a hashmap which can let you know which entities can be attacked from each point and then go through them at the same time.
    you can just mark them for attack if you need to check afterwards each entity attack which is exactly tied with another and decide to do what with them or decide at mark time by checking if the reverse of the attack is possible with the same exact numbers as well or not.

    if I want to tell you about philosophy , DOD is all about designing for your specific data and transformations and their frequency so it is hard to tell anything special without specific usecases