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

Working on two groups of entities in a system

Discussion in 'Entity Component System' started by Tazadar66, Sep 10, 2018.

  1. Tazadar66

    Tazadar66

    Joined:
    Aug 27, 2013
    Posts:
    57
    Hello everybody,

    I am currently discovering ECS.
    I would like to know if what I am doing is the correct with ECS...

    I am working on the unit selection with ECS.

    Right now you have an unique Entity which is an UnitSelector.
    When you click your left mouse button you add a Component to this entity called StartSelection which stores the start position.
    When you release your left click you add the EndSelection Component containing the end position.

    To Handle selection I have a System which requires two groups.
    The first group contains Entities which have Unit & Position Component.
    The second group contains Entities which have an EndSelection & StartSelection Component.

    That means I have to do two injects in one system.(First group & Second Group)
    In my system I will have something like this :

    Code (CSharp):
    1.  
    2. [Inject] private Group1 m_Group1;
    3. [Inject] private Group2 m_Group2;
    4.  
    5. protected override void OnUpdate()
    6. {
    7.    for (int j = 0; j != m_Group2.Length; j++)
    8.    {
    9.        for (int i = 0; i != m_Group1.Length; i++)
    10.        {
    11.        // Check if it is inside the selection...
    12.        }
    13.    }
    14. }
    Is it the best way of handling it? Please let me know if I am doing something wrong.

    Thank you.
     
    Last edited: Sep 10, 2018
  2. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,594
    In my understanding, is nothing wrong about this approach.
    Seams sensible.
    I have used it myself in few places.

    But I would like, to hear others comments as well.
     
    Tazadar66 likes this.
  3. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,594
    What I forgot, and I would like to add, put these in a job, or job parallel for of course.
     
  4. Tazadar66

    Tazadar66

    Joined:
    Aug 27, 2013
    Posts:
    57
    What do you mean ?
     
  5. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,594
  6. jamiebrynes

    jamiebrynes

    Joined:
    Sep 12, 2017
    Posts:
    18
    Instead of storing the positions in components, why not handle it all in the system so you don't need two groups?

    Something like:

    Code (CSharp):
    1.  
    2. public class UnitSelectionSystem : ComponentSystem
    3. {
    4.     private ComponentGroup allUnitsGroup;
    5.  
    6.     private bool triggerSelection;
    7.     private Vector3 selectionStartPoint;
    8.     private Vector3 selectionEndPoint;
    9.  
    10.     protected override OnCreateManager(int capacity)
    11.     {
    12.         base.OnCreateManager(capacity);
    13.  
    14.         allUnitsGroup = CreateComponentGroup(ComponentType.Readonly<Position>(), ComponentType.Readonly<Unit>());
    15.     }
    16.  
    17.     protected override OnUpdate()
    18.     {
    19.        
    20.         if (Input.GetMouseButtonDown(0))
    21.         {
    22.             selectionStartPoint = Input.mousePosition;
    23.         }
    24.  
    25.         if (!Input.GetMouseButton(0))
    26.         {
    27.             triggerSelection = true;
    28.             selectionEndPoint = Input.mousePosition;
    29.         }
    30.  
    31.         if (triggerSelection)
    32.         {
    33.             var positions = allUnitsGroup.GetComponentDataArray<Position>();
    34.             var entities = allUnitsGroup.GetEntityArray();
    35.  
    36.             for (var i = 0; i < positions.Length; i ++)
    37.             {
    38.                 if (IsUnitInSelection(positions[i]))
    39.                 {
    40.                     PostUpdateCommands.AddComponent(entities[i], new SelectedComponent());
    41.                 }
    42.             }
    43.  
    44.             triggerSelection = false;
    45.         }
    46.     }
    47.  
    48.     private bool IsUnitInSelection(Position position)
    49.     {
    50.         // Implementation
    51.     }
    52. }
    You can even jobify the calculation and adding of the components.
     
    Tazadar66 likes this.
  7. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,594
    This approach may be not suitable, when multiple systems are to be affecting same component of entities.
     
  8. jamiebrynes

    jamiebrynes

    Joined:
    Sep 12, 2017
    Posts:
    18
    Doesn't the automatic dependency management of systems provide those guarantees for you? Otherwise you have to specify a strict ordering of systems and jobs.
     
  9. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,594
    The point of having two groups, is to bring two sets of filtered entities and do operation on them in one job for example.
    But that depends on requirement, either solution may be sufficient. However, OP question is about 2 groups explicitly.

    Ordering may be required, if the design needs it.
     
    Tazadar66 likes this.
  10. Tazadar66

    Tazadar66

    Joined:
    Aug 27, 2013
    Posts:
    57
    Thank you for your help. I will try to make a Job as you showed me.
    If I understand correctly I do a job which works on all Units.
    In this job there is a for loop on Entities which have an EndSelection & StartSelection Component.