Search Unity

Injected arrays deallocated after adding component to entity

Discussion in 'Entity Component System' started by eizenhorn, Apr 24, 2018.

  1. eizenhorn

    eizenhorn

    Joined:
    Oct 17, 2016
    Posts:
    2,683
    Code (CSharp):
    1. public struct Worker : IComponentData
    2. {
    3. }
    4.  
    5. public class WorkerComponent : ComponentDataWrapper<Worker>
    6. {
    7. }
    8.  
    9.  
    10. public class SomeSystem : ComponentSystem
    11. {
    12.     public struct SomeStructData
    13.     {
    14.         public int someValue;
    15.     }
    16.  
    17.     public struct SomeGroup
    18.     {
    19.         public ComponentArray<SomeMonoBehaviourComponent> monoComponent;
    20.         public SubtractiveComponent<WorkerComponent> notWorker;
    21.         public EntityArray Entity;
    22.         public int Length;
    23.     }
    24.  
    25.     [Inject] public SomeGroup someGroup;
    26.  
    27.     public struct SomeJob : IJobParallelFor
    28.     {
    29.         public NativeQueue<SomeStructData>.Concurrent someData;
    30.  
    31.         public void Execute(int index)
    32.         {
    33.             //DO STUF
    34.         }
    35.     }
    36.  
    37.     protected override void OnUpdate()
    38.     {
    39.         NativeQueue<SomeStructData> someData = new NativeQueue<SomeStructData>(Allocator.Temp);
    40.         var job = new SomeJob
    41.         {
    42.             someData = someData
    43.         };
    44.         job.Schedule(someGroup.Length, Mathf.CeilToInt(someGroup.Length / 8)).Complete();
    45.  
    46.         while (someData.Count > 0)
    47.         {
    48.             SomeStructData data = someData.Dequeue();
    49.             for (int i = 0; i < data.someValue; i++)
    50.             {
    51.                 if (someGroup.Length > 0)
    52.                 {
    53.                     EntityManager.AddComponent(someGroup.Entity[0], typeof(WorkerComponent));
    54.                    // ^^^^^^ after first adding, this place thrown error - NativeArray has been deallocated, as i know AddComponent in EntityManager is one of synch points
    55.                 }
    56.             }
    57.         }
    58.     }
    59. }
    How i can add new components in one Update loop in hybrid ECS?
    Also i tried to use EntityCommandBuffer:
    Code (CSharp):
    1. public struct Worker : IComponentData
    2. {
    3. }
    4.  
    5. public class WorkerComponent : ComponentDataWrapper<Worker>
    6. {
    7. }
    8.  
    9.  
    10. public class SomeSystem : ComponentSystem
    11. {
    12.     public struct SomeStructData
    13.     {
    14.         public int someValue;
    15.     }
    16.  
    17.     public struct SomeGroup
    18.     {
    19.         public ComponentArray<SomeMonoBehaviourComponent> monoComponent;
    20.         public SubtractiveComponent<WorkerComponent> notWorker;
    21.         public EntityArray Entity;
    22.         public int Length;
    23.     }
    24.  
    25.     [Inject] public SomeGroup someGroup;
    26.  
    27.     public struct SomeJob : IJobParallelFor
    28.     {
    29.         public NativeQueue<SomeStructData>.Concurrent someData;
    30.  
    31.         public void Execute(int index)
    32.         {
    33.             //DO STUF
    34.         }
    35.     }
    36.  
    37.     protected override void OnUpdate()
    38.     {
    39.         NativeQueue<SomeStructData> someData = new NativeQueue<SomeStructData>(Allocator.Temp);
    40.         var job = new SomeJob
    41.         {
    42.             someData = someData
    43.         };
    44.         job.Schedule(someGroup.Length, Mathf.CeilToInt(someGroup.Length / 8)).Complete();
    45.  
    46.         if (someData.Count > 0)
    47.         {
    48.             EntityCommandBuffer buff = new EntityCommandBuffer();
    49.             while (someData.Count > 0)
    50.             {
    51.                 SomeStructData data = someData.Dequeue();
    52.                 for (int i = 0; i < data.someValue; i++)
    53.                 {
    54.                     if (someGroup.Length > 0)
    55.                     {
    56.                         buff.AddComponent(someGroup.Entity[0], new Worker());
    57.                         // ^^^This place handle error every time - Null Reference
    58.                         //Interesting moment - EntityManager.AddComponent and EntityCommandBuffer.AddComponent - different, why?!
    59.                     }
    60.                 }
    61.             }
    62.             buff.Playback(EntityManager);
    63.         }
    64.  
    65.     }
    66. }
     
    Last edited: Apr 24, 2018
  2. eizenhorn

    eizenhorn

    Joined:
    Oct 17, 2016
    Posts:
    2,683
    Any solutions?
     
  3. Spy-Shifty

    Spy-Shifty

    Joined:
    May 5, 2011
    Posts:
    546
    take use of:
    Code (CSharp):
    1. PostUpdateCommand.CreateEntity()
    2. PostUpdateCommand.AddComponent(new SomeData())
    3. ...
     
    eizenhorn likes this.
  4. eizenhorn

    eizenhorn

    Joined:
    Oct 17, 2016
    Posts:
    2,683
    Hmm, PostUpdateCommands is also EntityCommandBuffer...but in my own EntityCommandBuffer - m_Data (in EntityCommandBuffer.cs) is null.
    PostUpdateCommands basically does what it takes (as I imagined the work of the buffer), but in my case there is a nuance, I do not need to create Entity, I just add the component to the existing one:

    PostUpdateCommands.AddComponent (m_Citizens.Entity [j], new Worker ());

    But then the fun begins, after adding the EntityArray component is not updated correctly and in m_Citizens there are entities on which I added Worker, despite the presence:

    public SubtractiveComponent <WorkerComponent> NotWorker;
     
  5. eizenhorn

    eizenhorn

    Joined:
    Oct 17, 2016
    Posts:
    2,683
    Oh, I'm sorry, I completely overlooked that I added the WorkerComponent wrapper as T in to SubtractiveComponent<T>, not Worker: IComponentData :)