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 Design Problem - Cross Components System

Discussion in 'Entity Component System' started by vincentchu_atalonventures, Aug 2, 2018.

  1. vincentchu_atalonventures

    vincentchu_atalonventures

    Joined:
    May 4, 2018
    Posts:
    16
    Hi all,

    Suppose I would like to have a system combining data with component groups "A, B" and "C, D" affecting component groups "E, F" and "G, H", does anyone has a suggested way to do it with Unity ECS?
     
    Last edited: Aug 2, 2018
  2. ldhongen1990

    ldhongen1990

    Joined:
    Dec 18, 2015
    Posts:
    61
    Do you have a proper case example? It's very difficult to understand the problem if it's that generic, component groups as in Struct containing datatype ready for injection? A B C D E F G and H are datatype in the struct or the struct itself?
     
  3. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,584
    Does shared component would do the job for you?
     
  4. vincentchu_atalonventures

    vincentchu_atalonventures

    Joined:
    May 4, 2018
    Posts:
    16
    Thanks for all your responses.

    Here is my concrete example, I am not sure if Shared Component can help on this.

    I have a game has Entity "Player, Pet, Speaker, Light", suppose there is a logic like this:

    There is an ownerId in PetComponent and playerId in PlayerComponent, if ownerId and playerId match, check playSound (boolean) and playLight (boolean) in PlayerComponent to trigger the number of LightComponent and SpeakerComponent in the Scene.


    Can anyone suggest me a correct way to implement this kind of logic with Unity ECS?
     

    Attached Files:

    Last edited: Aug 2, 2018
  5. ldhongen1990

    ldhongen1990

    Joined:
    Dec 18, 2015
    Posts:
    61
    Let me know if you guys find a better way to do this

    Code (CSharp):
    1.  
    2. class SceneDynamicSystem : ComponentSystem
    3. {
    4.     struct Players
    5.     {
    6.         public readonly int Length;
    7.         public ComponentArray<PlayerComponent> value;
    8.     }
    9.  
    10.     struct Pets
    11.     {
    12.         public readonly int Length;
    13.         public ComponentArray<PetComponent> value;
    14.     }
    15.  
    16.     struct Lights
    17.     {
    18.         public readonly int Length;
    19.         public ComponentArray<Light> value;
    20.     }
    21.  
    22.     struct Speakers
    23.     {
    24.         public readonly int Length;
    25.         public ComponentArray<SpeakerComponent> value;
    26.     }
    27.  
    28.     [Inject] private Players _players;
    29.     [Inject] private Pets _pets;
    30.     [Inject] private Lights _lights;
    31.     [Inject] private Speakers _speakers;
    32.  
    33.  
    34.     protected override void OnUpdate()
    35.     {
    36.         int playSoundCounter = 0;
    37.         int playLightCounter = 0;
    38.         for (int i = 0; i < _players.Length; ++i)
    39.         {
    40.             for (int j = 0; j < _pets.Length; ++j)
    41.             {
    42.                 if (_players.value[i].playerId == _pets.value[i].ownerId)
    43.                 {
    44.                     if (_players.value[i].playSound) { ++playSoundCounter; }
    45.                     if (_players.value[i].playLight) { ++playLightCounter; }
    46.                 }
    47.             }
    48.         }
    49.  
    50.         //Turn on light
    51.         for (int i = 0; i < _lights.Length; ++i)
    52.         {
    53.             _lights.value[i].gameObject.SetActive(true);
    54.  
    55.             if (i >= playLightCounter) { break; }
    56.         }
    57.  
    58.         //Turn on speakers
    59.         for (int i = 0; i < _speakers.Length; ++i)
    60.         {
    61.             _speakers.value[i].gameObject.SetActive(true);
    62.  
    63.             if (i >= playSoundCounter) { break; }
    64.         }
    65.  
    66.  
    67.         //Update once on init, stop the system
    68.         //supposed you only want to update once, else remove
    69.         //to keep updating, but you may want to restructure
    70.         //player with petid matching to improve performance.
    71.         Enabled = false;
    72.     }
    73. }
    74.  
    75.  
     
  6. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,635
    If you were using ComponentDatas you could use GetComponentDataFromEntity instead of looping so much

    Code (CSharp):
    1.  
    2.             var players = EntityManager.GetComponentDataFromEntity<PlayerComponent>();
    3.  
    4.             int playSoundCounter = 0;
    5.             int playLightCounter = 0;
    6.             for (int j = 0; j < _pets.Length; ++j)
    7.             {
    8.                 var player = players[_pets.value[i].ownerId];
    9.                 if (player.playSound) { ++playSoundCounter; }
    10.                 if (player.playLight) { ++playLightCounter; }
    11.             }
    If not all pets have owners, do a
    if (players.Exists(_pets.value[i].ownerId))
     
  7. vincentchu_atalonventures

    vincentchu_atalonventures

    Joined:
    May 4, 2018
    Posts:
    16
    My current approach is to create a separated component group for storing the linked player pet group

    Code (CSharp):
    1. public class Logic01Component : MonoBehaviour
    2. {
    3.     public bool dirty;
    4.     public List<LinkedPlayerPetGroup> LinkedPlayerPetGroupList = new List<LinkedPlayerPetGroup>();
    5. }
    6.  
    7. public class LinkedPlayerPetGroup
    8. {
    9.     public PlayerComponent PlayerComponent;
    10.     public PetComponent PetComponent;
    11.  
    12.     public LinkedPlayerPetGroup(PlayerComponent _PlayerComponent, PetComponent _PetComponent)
    13.     {
    14.         PlayerComponent = _PlayerComponent;
    15.         PetComponent = _PetComponent;
    16.     }
    17. }
    Code (CSharp):
    1. public class GameLogic1System : ComponentSystem {
    2.     private struct Logic01ComponentGroup
    3.     {
    4.         public Logic01Component Logic01Component;
    5.     }
    6.  
    7.     private struct SpeakerComponentGroup
    8.     {
    9.         public SpeakerComponent SpeakerComponent;
    10.     }
    11.  
    12.     private struct LightComponentGroup
    13.     {
    14.         public LightComponent LightComponent;
    15.     }
    16.  
    17.     protected override void OnUpdate()
    18.     {
    19.         int lightCount = 0;
    20.         int soundCount = 0;
    21.         foreach (var entity in GetEntities<Logic01ComponentGroup>())
    22.         {
    23.             // Currently only have 1 Logic01ComponentGroup
    24.             if (!entity.Logic01Component.dirty)
    25.               return;
    26.             foreach (var lc in entity.Logic01Component.LinkedPlayerPetGroupList)
    27.             {
    28.                 lightCount += lc.PlayerComponent.playLight ? 1 : 0;
    29.                 soundCount += lc.PlayerComponent.playSound ? 1 : 0;
    30.             }
    31.         }
    32.    
    33.         int speakerIndex = 0;
    34.         foreach (var entity in GetEntities<SpeakerComponentGroup>())
    35.             entity.SpeakerComponent.isActive = speakerIndex++ < lightCount;
    36.  
    37.         int lightIndex = 0;
    38.         foreach (var entity in GetEntities<LightComponentGroup>())
    39.             entity.LightComponent.isActive = lightIndex++ < soundCount;
    40.     }
    41. }
    But this approach still has problem such as:
    1. The order of SpeakerComponent and LightComponent turned on is not following the scene hierarchy in Hybrid ECS
    2. The selection of components required for a system being another system ( Or this is acceptable? )
    3. There are so many sub-classes for each pair of linkage
     
    Last edited: Aug 3, 2018