Search Unity

Noob ECS Questions

Discussion in 'Data Oriented Technology Stack' started by francois85, May 11, 2019.

  1. francois85

    francois85

    Joined:
    Aug 11, 2015
    Posts:
    491
    Just starting on ECS and had a Questions (Please let me know if im on the wrong forum)

    So I have a tile based game. Im trying to build the board using ECS. Ive started by setting up my components, entities and now the build system.

    This is where im confused, i only see a OnUpdate() function. How do I control the execution of this function.I only need to build my hex tiles once ( populate 2 component arrays) how do I break out of this system or decide when to run the system.

    Code (csharp):
    1.  
    2. namespace Test.HexSphereECS
    3. {
    4.  
    5.     /// <summary>
    6.     /// System for creating a hexSphere
    7.     /// </summary>
    8.     public class HexSphereBuildSystem : ComponentSystem
    9.     {
    10.         // Must implement for ComponentSystem
    11.         protected override void OnUpdate()
    12.         {
    13.              // Build my Sphere
    14.         }
    15.     }
    16. }
    17.  
     
  2. snacktime

    snacktime

    Joined:
    Apr 15, 2013
    Posts:
    2,169
    You have OnCreateManager/OnDestroyManager as virtual methods you can override. Those are where you should do your setup/teardown, allocation/dispose persistent native containers, etc.. Like below. OnDestroyManager same pattern.

    Code (csharp):
    1.  
    2. protected override void OnCreateManager()
    3.         {
    4.             base.OnCreateManager();
    5.            
    6.         }
    7.  
     
  3. francois85

    francois85

    Joined:
    Aug 11, 2015
    Posts:
    491
    Thank you for answer, lots of new stuff here
     
  4. francois85

    francois85

    Joined:
    Aug 11, 2015
    Posts:
    491
    One more question, If I need a nativeArray of entities that will be used my multiple systems how and where do I define store it.

    Code (csharp):
    1.  
    2.  public static  NativeArray<Entity> tileArray = new NativeArray<Entity>(100, Allocator.Persistent
    3. );
    4.  
     
  5. supron

    supron

    Joined:
    Aug 24, 2013
    Posts:
    31
    Such array is unnecessary. Actually, it's against ECS principles. You should add a common component to these entities and use EntityQuery to get all the chunks with your component. ArchetypeChunk has GetNativeArray function. It returns NativeArray of entities from the chunk. You can access it from different systems. This approach is better because:
    1. You don't need a static array of entities (it's bad design anyway)
    2. You have more efficient access to component data (linear memory block per chunk, and you don't have to ask for data of every entity in your array)
    3. Entity array is always up to date. Added/removed component will be immediately updated, and all other systems will get updated NativeArrays form queries.

    It's also easier to introduce multithreading without static arrays with global access. Job system has great race condition detection and automatic dependency tracking. You should stick to the ECS principles and soon everything will be way easier.
     
  6. francois85

    francois85

    Joined:
    Aug 11, 2015
    Posts:
    491
    Got it thanks heaps for the help, Ok given what I think I understood I jumped the gun here, Im not even up to the point of accessing the entities. So what im trying to refactor into ECS is a hexSphere sudivision from an Icosahedron. So I need to create the base Icosahedron first and then access those components using EntityQuery ( Like everything in ESC first time ive heard of it)

    Here is what I came up with, any critiques would be appreciated.

    My questions
    1) I noticed that Im required to implement OnUpdate() but im not using it, seems like something is wrong.
    2) Is the BootstrapECS class needed ? Only thing im doing here is defining an EntityArchetype. Is this the correct place to do it in this design pattern ?


    Code (csharp):
    1.  
    2. namespace TEST.HexSphereECS
    3. {
    4.     /// <summary>
    5.     /// </summary>
    6.     public class BootstrapECS
    7.     {
    8.         public static EntityArchetype tileArchetype;
    9.  
    10.  
    11.         /// <summary>
    12.         /// </summary>
    13.         [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
    14.         public static void Init()
    15.         {
    16.             // Create EntityManager
    17.             EntityManager entityManager = World.Active.EntityManager;
    18.  
    19.             // Create Entity Archetype instantiation
    20.             tileArchetype = entityManager.CreateArchetype(typeof(HexVertexComponent) );
    21.  
    22.         }
    23.     }
    24. }
    25.  
    26.  
    Code (csharp):
    1.  
    2. namespace TEST.HexSphereECS
    3. {
    4.     /// <summary>
    5.     /// HexTile - A Hextile is a single hex (or sometimes pentagon)
    6.     /// in the hex tiled planet. It is a single vertex of the mesh
    7.     /// </summary>
    8.     public struct HexVertexComponent : IComponentData
    9.     {
    10.         #region FLIELDS --------------------------------------------------------
    11.  
    12.         public int hexIndex;
    13.         public float3 position;
    14.         public int connectedTriA;                                               //Index into the HexTri array that share this hex
    15.         public int connectedTriB;                                               //Index into the HexTri array that share this hex
    16.         public int connectedTriC;                                               //Index into the HexTri array that share this hex
    17.         public int connectedTriD;                                               //Index into the HexTri array that share this hex
    18.         public int connectedTriE;                                               //Index into the HexTri array that share this hex
    19.         public int connectedTriF;                                               //Index into the HexTri array that share this hex
    20.  
    21.         #endregion
    22.  
    23.     }
    24.  
    25. }
    26.  
    27.  
    Code (csharp):
    1.  
    2. namespace TEST.HexSphereECS
    3. {
    4.  
    5.     /// <summary>
    6.     /// System for creating a hexSphere
    7.     /// </summary>
    8.     public class HexSphereBuildSystem : ComponentSystem
    9.     {
    10.         #region FIELDS ---------------------------------------------------------
    11.  
    12.         EntityManager entityManager = World.Active.EntityManager;               // Reference to entityManager
    13.  
    14.         #endregion
    15.  
    16.  
    17.         #region METHODS --------------------------------------------------------
    18.  
    19.         /// <summary>
    20.         /// OnUpdate, Must implement for ComponentSystem
    21.         /// </summary>
    22.         protected override void OnUpdate()
    23.         {
    24.             Debug.Log("In system");
    25.         }
    26.  
    27.         /// <summary>
    28.         /// OnCreateManager
    29.         /// </summary>
    30.         protected override void OnCreateManager()
    31.         {
    32.             //
    33.             // Build Icosahedron
    34.             BuildIcosahedronEntities(1.0f);
    35.         }
    36.  
    37.  
    38.         /// <summary>
    39.         /// Create the lvl 0 Icosahedron.
    40.         /// </summary>
    41.         private void BuildIcosahedronEntities(float raduis)
    42.         {
    43.             Entity tileEntity = EntityManager.CreateEntity(typeof(HexVertexComponent));
    44.             EntityManager.SetComponentData(tileEntity, new HexVertexComponent { hexIndex = 0, position = new float3(0.723606f, 0.0f, 1.17082f), connectedTriA = -1, connectedTriB = -1, connectedTriC = -1, connectedTriD = -1, connectedTriE = -1, connectedTriF = -1 });
    45.  
    46.             tileEntity = EntityManager.CreateEntity(typeof(HexVertexComponent));
    47.             EntityManager.SetComponentData(tileEntity, new HexVertexComponent { hexIndex = 1, position = new float3(0.0f, 1.17082f, 0.723606f), connectedTriA = -1, connectedTriB = -1, connectedTriC = -1, connectedTriD = -1, connectedTriE = -1, connectedTriF = -1 });
    48.  
    49.             tileEntity = EntityManager.CreateEntity(typeof(HexVertexComponent));
    50.             EntityManager.SetComponentData(tileEntity, new HexVertexComponent { hexIndex = 2, position = new float3(-0.723606f, 0.0f, 1.17082f), connectedTriA = -1, connectedTriB = -1, connectedTriC = -1, connectedTriD = -1, connectedTriE = -1, connectedTriF = -1 });
    51.  
    52.             tileEntity = EntityManager.CreateEntity(typeof(HexVertexComponent));
    53.             EntityManager.SetComponentData(tileEntity, new HexVertexComponent { hexIndex = 3, position = new float3(0.0f, -1.17082f, 0.723606f), connectedTriA = -1, connectedTriB = -1, connectedTriC = -1, connectedTriD = -1, connectedTriE = -1, connectedTriF = -1 });
    54.  
    55.             tileEntity = EntityManager.CreateEntity(typeof(HexVertexComponent));
    56.             EntityManager.SetComponentData(tileEntity, new HexVertexComponent { hexIndex = 4, position = new float3(0.723606f, 0.0f, -1.17082f), connectedTriA = -1, connectedTriB = -1, connectedTriC = -1, connectedTriD = -1, connectedTriE = -1, connectedTriF = -1 });
    57.  
    58.             tileEntity = EntityManager.CreateEntity(typeof(HexVertexComponent));
    59.             EntityManager.SetComponentData(tileEntity, new HexVertexComponent { hexIndex = 5, position = new float3(0.0f, -1.17082f, -0.723606f), connectedTriA = -1, connectedTriB = -1, connectedTriC = -1, connectedTriD = -1, connectedTriE = -1, connectedTriF = -1 });
    60.  
    61.             tileEntity = EntityManager.CreateEntity(typeof(HexVertexComponent));
    62.             EntityManager.SetComponentData(tileEntity, new HexVertexComponent { hexIndex = 6, position = new float3(-0.723606f, 0.0f, -1.17082f), connectedTriA = -1, connectedTriB = -1, connectedTriC = -1, connectedTriD = -1, connectedTriE = -1, connectedTriF = -1 });
    63.  
    64.             tileEntity = EntityManager.CreateEntity(typeof(HexVertexComponent));
    65.             EntityManager.SetComponentData(tileEntity, new HexVertexComponent { hexIndex = 7, position = new float3(0.0f, 1.17082f, -0.723606f), connectedTriA = -1, connectedTriB = -1, connectedTriC = -1, connectedTriD = -1, connectedTriE = -1, connectedTriF = -1 });
    66.  
    67.             tileEntity = EntityManager.CreateEntity(typeof(HexVertexComponent));
    68.             EntityManager.SetComponentData(tileEntity, new HexVertexComponent { hexIndex = 8, position = new float3(1.17082f, -0.723606f, 0.0f), connectedTriA = -1, connectedTriB = -1, connectedTriC = -1, connectedTriD = -1, connectedTriE = -1, connectedTriF = -1 });
    69.  
    70.             tileEntity = EntityManager.CreateEntity(typeof(HexVertexComponent));
    71.             EntityManager.SetComponentData(tileEntity, new HexVertexComponent { hexIndex = 9, position = new float3(1.17082f, 0.723606f, 0.0f), connectedTriA = -1, connectedTriB = -1, connectedTriC = -1, connectedTriD = -1, connectedTriE = -1, connectedTriF = -1 });
    72.  
    73.             tileEntity = EntityManager.CreateEntity(typeof(HexVertexComponent));
    74.             EntityManager.SetComponentData(tileEntity, new HexVertexComponent { hexIndex = 10, position = new float3(-1.17082f, 0.723606f, 0.0f), connectedTriA = -1, connectedTriB = -1, connectedTriC = -1, connectedTriD = -1, connectedTriE = -1, connectedTriF = -1 });
    75.  
    76.             tileEntity = EntityManager.CreateEntity(typeof(HexVertexComponent));
    77.             EntityManager.SetComponentData(tileEntity, new HexVertexComponent { hexIndex = 11, position = new float3(-1.17082f, -0.723606f, 0.0f), connectedTriA = -1, connectedTriB = -1, connectedTriC = -1, connectedTriD = -1, connectedTriE = -1, connectedTriF = -1 });
    78.  
    79.         }
    80.  
    81.         #endregion
    82.  
    83.     }
    84. }
    85.  
    86.  
     
  7. jooleanlogic

    jooleanlogic

    Joined:
    Mar 1, 2018
    Posts:
    327
    ComponentSystem already has an accessor for EntityManager so no need to create a reference for it in HexSphereBuildSystem.

    I'm not sure myself where is the best place to bootstrap stuff but what you're doing looks fine. If you're spawning entities as part of level creation, it might be best to put it all in a single level bootstrap system but if they're related to the functioning of a specific system, then individual systems might be the best place.
    E.g. a TimerSystem that ticks time might itself create the singleton Timer entity that it operates on.

    OnUpdate is where you process the queries for a system.
    As an example.
    Code (CSharp):
    1. OnUpdate(){
    2.     Entities.ForEach<HexVertexComponent>( (ref HexVertexComponent hexVertex) => {
    3.         // Do something with hexVertex;
    4.     });
    5. }
    The idea being that a system performs an operation(s) on a set of entities that match a query.
    The system knows what queries have been registered with it (HexVertexComponent in the above eg) and OnUpdate() won't run if there are no entities that match the query.
    You can also explicitly create queries like so which you need sometimes if using multiple queries or chunk iteration or jobs:
    Code (CSharp):
    1. class HexSphereBuildSystem : ComponentSystem {
    2.     EntityQuery _query;
    3.  
    4.     OnCreate() {
    5.         _query = GetEntityQuery( typeof(HexVertexComponent), typeof(MyTagComponent) );
    6.         BuildIcosahedronEntities(1.0f);
    7.     }
    8.  
    9.     OnUpdate(){
    10.         Entities.With(_query).ForEach<HexVertexComponent>( (ref HexVertexComponent hexVertex) => {
    11.             // Do something with hexVertex;
    12.         });
    13.     }
    14.     ...
    15. }
     
    francois85 likes this.
  8. francois85

    francois85

    Joined:
    Aug 11, 2015
    Posts:
    491
    This is great info thanks so much Going to play with this to make sure I understand it and I’ll return with more questions. Thanks again

    I should probably start a difference thread since I when way off topic here