Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

ECS, and passing data

Discussion in 'Entity Component System' started by ImmortalDax, Aug 1, 2018.

  1. ImmortalDax

    ImmortalDax

    Joined:
    Jul 29, 2018
    Posts:
    5
    I have been struggling with how to pass data, giving my minions the jobs is something I can't figure out how to do. I have a system that controls his movement to get him in the right place. It's simplistic right now, something I am struggling with is how do I feed the location information to the movement system(x,y).
     
  2. ldhongen1990

    ldhongen1990

    Joined:
    Dec 18, 2015
    Posts:
    61
    Here is how I will roughly do it, in ECS you "don't pass data around", you tell the system what you want and they will get it for you, at least that is what I understood. The code is open for suggestions and improvement as part of my learning too.

    Code (CSharp):
    1. using Unity.Entities;
    2. using UnityEngine;
    3. using Unity.Collections;
    4. using Unity.Burst;
    5. using Unity.Jobs;
    6.  
    7.  
    8. public struct TargetDestination : IComponentData
    9. {
    10.     public Vector3 position;
    11. }
    12.  
    13. //Pure marker types (tagging purposes only)
    14. public struct Player : IComponentData { }
    15. public struct Minion : IComponentData { }
    16. public struct TrackPlayer : IComponentData { }
    17.  
    18. //System tracks player and update target destination
    19. class MinionTrackPlayerSystem : ComponentSystem
    20. {
    21.     struct Players
    22.     {
    23.         public readonly int Length;
    24.         public ComponentDataArray<Player> players;
    25.         public EntityArray entities;
    26.         public ComponentArray<Transform> position;
    27.     }
    28.  
    29.     struct Minions
    30.     {
    31.         public readonly int Length;
    32.         public ComponentDataArray<Minion> minions;
    33.         public EntityArray entities;
    34.         public ComponentDataArray<TargetDestination> destinations;
    35.         public ComponentDataArray<TrackPlayer> marker; //Anything with this component tag tracks the player
    36.     }
    37.  
    38.     [Inject] private Players _players;
    39.     [Inject] private Minions _minions;
    40.  
    41.     protected override void OnUpdate()
    42.     {
    43.         if (_players.Length <= 0) { return; }
    44.  
    45.         //Minion tracks first found player
    46.         var firstPlayerPos = _players.position[0];
    47.         for (int i = 0; i < _minions.Length; ++i)
    48.         {
    49.             var dest = _minions.destinations[i];
    50.             dest.position = firstPlayerPos.position;
    51.             _minions.destinations[i] = dest;
    52.         }
    53.     }
    54. }
    55.  
    56. //System move anything with a target destination towards it
    57. class TargetDestinationMovementSystem : ComponentSystem
    58. {
    59.     struct Entities
    60.     {
    61.         public readonly int Length;
    62.         public ComponentDataArray<TargetDestination> target;
    63.         public ComponentArray<Transform> trans;
    64.     }
    65.  
    66.     [Inject] private Entities _entities;
    67.  
    68.     protected override void OnUpdate()
    69.     {
    70.         for (int i = 0; i < _entities.Length; ++i)
    71.         {
    72.             MoveTowards(_entities.trans[i], _entities.target[i].position);
    73.         }
    74.     }
    75.  
    76.     public void MoveTowards(Transform source, Vector3 target)
    77.     {
    78.         //TODO: Implement movement towards behavior
    79.     }
    80. }
     
  3. ImmortalDax

    ImmortalDax

    Joined:
    Jul 29, 2018
    Posts:
    5
    I think my question is more where would the information come from. Should I make a script that generates jobs?
     
  4. ImmortalDax

    ImmortalDax

    Joined:
    Jul 29, 2018
    Posts:
    5
    Or have a global script that the minions can get the jobs from.
     
  5. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,635
    For my AI system I have a IssueOrderSystem which issues orders to units who do not currently have an order.

    Then I have systems for each type of order - i.e. harvest, build, move etc.
     
  6. Vacummus

    Vacummus

    Joined:
    Dec 18, 2013
    Posts:
    191
    Passing jobs to your minions is not how ECS works. ECS is a data oriented programming pattern, so things get a lot easier when you think about it from a data oriented perspective, which is: To solve my problem, what is the data that I need and what systems do I need that will read from and write to this data.

    You are on the right track so far with MovementSystem, but your question of where this movement information comes from entirely depends on the problem you are trying to solve. Are you trying get your minions to follow another entity with an (x,y) position? Are they following a set path? Are they bouncing around some random paths? Are they following your mouse input? But for the sake of an example, lets try to solve the problem of your minions following another entity with an (x,y) position.

    The data we need to solve this problem is simple:
    • PositionComponent { x, y }
    • MovementSpeedComponent { speed }
    • MoveToPositionComponent { x, y }
    • FollowEntityComponent { EntityId }
    And here are the systems:
    • MoveToPositionSystem
      • Takes in the PositionComponent, MoveToPositionComponent, MovementSpeedComponent
      • Reads the (x,y) values from the MoveToPositionComponent
      • Reads the speed value from the MovementSpeedComponent
      • Calculates the new position based on read values,
      • Writes the calculated position to the (x,y) values of the PositionComponent
    • FollowEntitySystem
      • Takes in the FollowEntityComponent and the MoveToPositionComponent.
      • It reads the entityId value from the FollowEntityComponent
      • Gets the PositionComponent from that entity. With that PositionComponent it will write to the (x,y) values of the MoveToPositionComponent.
    Then for your minions you just add the following components and your good to go:
    • minionEntity.addComponent<PositionComponent>(...);
    • minionEntity.addComponent<MoveToPositionComponent>(...);
    • minionEntity.addComponent<MovementSpeedComponent>(...);
    • minionEntity.addComponent<FollowEntityComponent>(new FollowEntityComponent { entityId = lordEntity });
    That's it! Notice that I never did anything with minions in my data and my systems. This is the beauty of ECS, behavior and data is decoupled allowing you easily write modular and reusable code that scales well. Hope this helps.
     
    Uglysluggers, jmcusack and Antypodish like this.
  7. ldhongen1990

    ldhongen1990

    Joined:
    Dec 18, 2015
    Posts:
    61
    His question is a bit vague, easy to confuse job with the job system in ECS. What he actually meant is he want to know how to implement a "Boss/Manager/Director/Hive Mind System" which will give out instruction to minions, that's what he meant by "passing data around", I came to realise that after he commented on my proposed code solution.
     
  8. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,584
    I like Vacummus response, as I definitely should find it useful in future project.
    But regarding "Hive Mind System", by my understanding, shared component is the right solution?
     
  9. ImmortalDax

    ImmortalDax

    Joined:
    Jul 29, 2018
    Posts:
    5
    Yes, sorry if I did not explain it well how do you think I should go about doing that? Like Vacummus said? or do you have another way?
     
  10. ldhongen1990

    ldhongen1990

    Joined:
    Dec 18, 2015
    Posts:
    61
    You can think about vacummus solution, but I think you also need a "Director" script to add and remove the ECS components mentioned by vacummus in the last paragraph. This "Director" script will then act as the mastermind overseeing your minions. Hence the type of ECS components you construct the minions with in your director script then determine their specific sets of behaviours, which can be added/removed at will.