Search Unity

Attempting to create a list of Entities to be used in another job

Discussion in 'Entity Component System' started by Matt_De_Boss_Developer, May 22, 2019.

  1. Matt_De_Boss_Developer

    Matt_De_Boss_Developer

    Joined:
    Oct 17, 2014
    Posts:
    46
    So at the current moment I am trying to create a list of entities within a system. The idea is that once I create the NativeList<Entity> with all of the entities that contain a certain Dyamic Buffer, that I will then pass each buffer attached to each entity to a IJobParallelFor Job that will then fill that Buffer. However, how am I supposed to handle the allocation and deallocation of the NativeList inside of my system, and is there a better way to be doing what I am attempting? Current code below:
    Code (CSharp):
    1. using Unity.Entities;
    2. using Unity.Jobs;
    3. using UnityEngine.Jobs;
    4. using Unity.Burst;
    5. using Unity.Collections;
    6. using UnityEngine;
    7.  
    8. using static Unity.Mathematics.math;
    9. using Unity.Mathematics;
    10.  
    11. public class VoxelGenerationSystem : JobComponentSystem
    12. {
    13.  
    14.     protected override void OnCreate()
    15.     {
    16.     }
    17.  
    18.     protected override JobHandle OnUpdate(JobHandle inputDeps)
    19.     {
    20.  
    21.         NativeList<Entity> entites = new NativeList<Entity>();
    22.  
    23.         var GrabVoxelDataEntities = new GrabVoxelDataEntities
    24.         {
    25.             entites = entites
    26.         }.Schedule(this, inputDeps);
    27.  
    28.         return GrabVoxelDataEntities;
    29.     }
    30.  
    31.     [BurstCompile]
    32.     struct GrabVoxelDataEntities : IJobForEachWithEntity<ChunkStatus>
    33.     {
    34.         //[DeallocateOnJobCompletion]
    35.         [WriteOnly]
    36.         public NativeArray<Entity> entites;
    37.  
    38.         public void Execute(Entity entity, int index, ref ChunkStatus c0)
    39.         {
    40.             entites[index] = entity;
    41.            
    42.         }
    43.  
    44.  
    45.  
    46.     }
    47.  
    48.  
    49.  
    50.  
    51.  
    52.  
    53.  
    54. }

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using Unity.Burst;
    5. using Unity.Jobs;
    6. using Unity.Collections;
    7. using Unity.Entities;
    8.  
    9. using static Unity.Mathematics.math;
    10. using Unity.Mathematics;
    11.  
    12.  
    13. [BurstCompile]
    14. public struct VoxelGenerationJob : IJobParallelFor
    15. {
    16.  
    17.  
    18.     public int SizeX;
    19.     public int SizeY;
    20.  
    21.     public float GridSize;
    22.  
    23.     public float3 initPos;
    24.  
    25.     [WriteOnly]
    26.     public DynamicBuffer<float> voxels;
    27.  
    28.  
    29.     public float time;
    30.  
    31.     public void Execute(int i)
    32.     {
    33.  
    34.         int iz = i / ((SizeX - 0) * (SizeY - 0));
    35.         int ib = i - (((SizeX - 0) * (SizeY - 0)) * iz);
    36.         int iy = ib / (SizeX - 0);
    37.         int ix = ib % (SizeX - 0);
    38.  
    39.         float z = iz;
    40.         float y = iy;
    41.         float x = ix;
    42.  
    43.  
    44.         voxels[i] = fbm_Noise((float3(x + time, y, z) + initPos)/(32 / GridSize),3);
    45.  
    46.     }
    47.  
    48.     float fbm_Noise(float3 pos, int octaves)
    49.     {
    50.  
    51.         float total = 0;
    52.         float frequency = 1;
    53.         float amplitude = 1;
    54.  
    55.        
    56.         for (int i = 0; i < octaves; i++)
    57.         {
    58.             total += noise.snoise((pos * frequency)) * amplitude;
    59.  
    60.  
    61.             amplitude *= .25f;
    62.             frequency *= 2f;
    63.         }
    64.  
    65.         return total;
    66.     }
    67.  
    68.  
    69.     float3 rotate(float3 p, float3x3 m)
    70.     {
    71.  
    72.         return float3(p.x * m.c0.x + p.x * m.c1.x + p.x * m.c2.x, p.y * m.c0.y + p.y * m.c1.y + p.y * m.c2.y, p.z * m.c0.z + p.z * m.c1.z + p.z * m.c2.z);
    73.     }
    74.  
    75.  
    76.     float Circle(float3 pos)
    77.     {
    78.         float x = pos.x - 8;
    79.         float y = pos.y - 8;
    80.         float z = pos.z - 8;
    81.  
    82.         return x * x + y * y + z * z - 36;
    83.  
    84.     }
    85.  
    86. }
    87.  
    88.  
     
  2. RoughSpaghetti3211

    RoughSpaghetti3211

    Joined:
    Aug 11, 2015
    Posts:
    1,709
    Im also interested in how to handle this as im running into a similar situation.
     
  3. Sarkahn

    Sarkahn

    Joined:
    Jan 9, 2013
    Posts:
    440
    I could be wrong but aren't you attempting to write to an empty array in your GrabVoxelEntities? Does that actually work?

    You could create an EntityQuery of your buffer entities then do eq.ToEntityArray to get a native array of all the relevant entities, then do an IJobParallelFor on that array, using BufferFromEntity to get your buffers
     
  4. Matt_De_Boss_Developer

    Matt_De_Boss_Developer

    Joined:
    Oct 17, 2014
    Posts:
    46
    KABAM ITS SUPER FREAKING FAST!!! I can officially create entities with a tag that states that voxel data needs to be created for a certain chunk. I spawned about 30,000 chunks and it chugged through with no harm to the main thread FPS!!! Code below:
    Code (CSharp):
    1. using Unity.Entities;
    2. using Unity.Jobs;
    3. using UnityEngine.Jobs;
    4. using Unity.Burst;
    5. using Unity.Collections;
    6. using UnityEngine;
    7.  
    8. using static Unity.Mathematics.math;
    9. using Unity.Mathematics;
    10.  
    11. public class VoxelGenerationSystem : JobComponentSystem
    12. {
    13.     EntityQuery eq;
    14.     BufferFromEntity<VoxelData> voxelData;
    15.  
    16.     protected override void OnCreate()
    17.     {
    18.         eq = World.Active.EntityManager.CreateEntityQuery(typeof(shouldGenerateIntialvoxelData));
    19.         //voxelData = GetBufferFromEntity<VoxelData>(false);
    20.     }
    21.  
    22.     protected override JobHandle OnUpdate(JobHandle inputDeps)
    23.     {
    24.         //eq = World.Active.EntityManager.CreateEntityQuery(typeof(VoxelData));
    25.  
    26.         NativeArray<Entity> entities = eq.ToEntityArray(Allocator.Persistent);
    27.  
    28.  
    29.  
    30.         if (entities.Length > 0)
    31.         {
    32.             World.EntityManager.RemoveComponent(entities[0], typeof(shouldGenerateIntialvoxelData));
    33.         }
    34.        
    35.         VoxelGenerationJob VGJob = new VoxelGenerationJob
    36.         {
    37.             SizeX = World.EntityManager.GetComponentData<ChunkStatus>(entities[0]).SizeX,
    38.             SizeY = World.EntityManager.GetComponentData<ChunkStatus>(entities[0]).SizeY,
    39.             voxelData = GetBufferFromEntity<VoxelData>(false),
    40.             entity = entities[0]
    41.         };
    42.         JobHandle VGHandle = VGJob.Schedule(17 * 17 * 17, 1);
    43.         //JobHandle[] voxelGenerationJobs = new JobHandle[entities.Length];
    44.  
    45.  
    46.  
    47.         //entities.Dispose();
    48.  
    49.         //throw new System.Exception();
    50.         return VGHandle;
    51.     }
    52.  
    53.    
    54.  
    55.  
    56.  
    57.  
    58.  
    59.  
    60.  
    61. }

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using Unity.Burst;
    5. using Unity.Jobs;
    6. using Unity.Collections;
    7. using Unity.Entities;
    8.  
    9. using static Unity.Mathematics.math;
    10. using Unity.Mathematics;
    11.  
    12.  
    13. [BurstCompile]
    14. public struct VoxelGenerationJob : IJobParallelFor
    15. {
    16.  
    17.  
    18.     public int SizeX;
    19.     public int SizeY;
    20.  
    21.  
    22.     //public float3 initPos;
    23.     [NativeDisableParallelForRestriction]
    24.     public BufferFromEntity<VoxelData> voxelData;
    25.  
    26.     public Entity entity;
    27.  
    28.    
    29.  
    30.  
    31.  
    32.     public void Execute(int i)
    33.     {
    34.         DynamicBuffer<VoxelData> voxels = voxelData[entity];
    35.         int iz = i / ((SizeX - 0) * (SizeY - 0));
    36.         int ib = i - (((SizeX - 0) * (SizeY - 0)) * iz);
    37.         int iy = ib / (SizeX - 0);
    38.         int ix = ib % (SizeX - 0);
    39.  
    40.         float z = iz;
    41.         float y = iy;
    42.         float x = ix;
    43.  
    44.  
    45.         VoxelData value = voxels[i];
    46.         value.value = fbm_Noise(float3(x, y, z),3);
    47.         voxels[i] = value;
    48.     }
    49.  
    50.     float fbm_Noise(float3 pos, int octaves)
    51.     {
    52.  
    53.         float total = 0;
    54.         float frequency = 1;
    55.         float amplitude = 1;
    56.  
    57.        
    58.         for (int i = 0; i < octaves; i++)
    59.         {
    60.             total += noise.snoise((pos * frequency)) * amplitude;
    61.  
    62.  
    63.             amplitude *= .25f;
    64.             frequency *= 2f;
    65.         }
    66.  
    67.         return total;
    68.     }
    69.  
    70.  
    71.     float3 rotate(float3 p, float3x3 m)
    72.     {
    73.  
    74.         return float3(p.x * m.c0.x + p.x * m.c1.x + p.x * m.c2.x, p.y * m.c0.y + p.y * m.c1.y + p.y * m.c2.y, p.z * m.c0.z + p.z * m.c1.z + p.z * m.c2.z);
    75.     }
    76.  
    77.  
    78.     float Circle(float3 pos)
    79.     {
    80.         float x = pos.x - 8;
    81.         float y = pos.y - 8;
    82.         float z = pos.z - 8;
    83.  
    84.         return x * x + y * y + z * z - 36;
    85.  
    86.     }
    87.  
    88. }
    89.  
    90.  
     
  5. RoughSpaghetti3211

    RoughSpaghetti3211

    Joined:
    Aug 11, 2015
    Posts:
    1,709
  6. Sarkahn

    Sarkahn

    Joined:
    Jan 9, 2013
    Posts:
    440
    I'm assuming you worked it out already but you're creating persistent array every time your system runs, you probably want to create with Allocator.TempJob and dispose it with [DeallocateAfterJobCompletion] in the job
     
  7. Matt_De_Boss_Developer

    Matt_De_Boss_Developer

    Joined:
    Oct 17, 2014
    Posts:
    46
    Yerp
     
  8. Razmot

    Razmot

    Joined:
    Apr 27, 2013
    Posts:
    346
    There is something that, even if it's a main thread api, is blazing fast when you want to massively "tag" entities ( with a IComponentData with no implementation, aka "tagComponent" ) :

    Code (CSharp):
    1.  
    2.      protected override void OnCreate()
    3.         {
    4.             var queryD = new EntityQueryDesc
    5.             {
    6.                 None = new ComponentType[] { typeof(ToCheck)},
    7.                 All = new ComponentType[] { ComponentType.ReadOnly<MyBuffer>() }
    8.             };
    9.             toCheckQ = GetEntityQuery(queryD);
    10. }
    11.  
    12. protected override void OnUpdate()
    13.         {
    14. EntityManager.AddComponent(toCheckQ, ComponentType.ReadOnly<ToCheck>());
    15. }
    It's very fast because (if I understand correctly) for the case of a tagComponent all it does is update an int index into the affected ChunkArchetypes.
     
    Sarkahn likes this.