Search Unity

How to Create Entities Based on Existing Component Values

Discussion in 'Entity Component System' started by S_Darkwell, Dec 16, 2018.

  1. S_Darkwell

    S_Darkwell

    Joined:
    Oct 20, 2013
    Posts:
    320
    Hello!

    What is the best way to create new Entities with Components based on the value of Components on existing Entities?

    Most straightforward approaches fail because the creation of new Entities invalidates the iteration of existing Entities. I would use PostUpdateCommands, except that I have to set the Component value of the new Entities.

    My current approach (below) is to create a List of values or IComponentData, iterate existing Entities and add to the List the Components/values to be updated, then iterate that List outside of Entity iteration to create the new Entities.

    Code (CSharp):
    1. using Unity.Entities;
    2. using System.Collections.Generic;
    3.  
    4. internal struct IncomingValueComponent : IComponentData {
    5.     public int Value;
    6. }
    7.  
    8. internal struct PositiveValueComponent : IComponentData {
    9.     public int Value;
    10. }
    11.  
    12. public class AllValuesInPositiveValuesOutSystem : ComponentSystem {
    13.     private EntityManager m;
    14.  
    15.     protected override void OnCreateManager() {
    16.         m = World.Active.GetOrCreateManager<EntityManager>();
    17.     }
    18.  
    19.     private struct Data {
    20.         public ComponentDataArray<IncomingValueComponent> Values;
    21.     }
    22.     [Inject] private Data data;
    23.  
    24.     protected override void OnUpdate() {
    25.         var positiveValues = new List<int>(data.Values.Length);
    26.         for (var i = 0; i < data.Values.Length; i++) {
    27.             if (data.Values[i].Value <= 0) {
    28.                 continue;
    29.             }
    30.  
    31.             positiveValues.Add(data.Values[i].Value);
    32.         }
    33.  
    34.         foreach (var v in positiveValues) {
    35.             var e = m.CreateEntity(ComponentType.Create<PositiveValueComponent>());
    36.             m.SetComponentData(e, new PositiveValueComponent {
    37.                 Value = v
    38.             });
    39.         }
    40.     }
    41. }
    Note: In actuality, I'm using Chunk iteration, not injection, but I've substituted injection here for clarity.

    What would be the preferred way of approaching this particular task?
    I'm certain my current approach is far from optimal.

    Thank you in advance and be well!
    - S.
     
  2. 5argon

    5argon

    Joined:
    Jun 10, 2013
    Posts:
    1,555
    PostUpdateCommand/EntityCommandBuffer can add/set the value of latest created Entity with the same command buffer by using the overload without entity.
     
    S_Darkwell likes this.
  3. S_Darkwell

    S_Darkwell

    Joined:
    Oct 20, 2013
    Posts:
    320
    @5argon,

    I literally became giddy when I saw your answer.
    I swapped out my code. PostUpdateCommand works perfectly.

    Thank you so very much!

    Be well!
    - S.
     
    5argon likes this.