Search Unity

ECS + Jobs - pass Entity array to job

Discussion in 'Entity Component System' started by Eldirfar, Oct 30, 2018.

  1. Eldirfar

    Eldirfar

    Joined:
    Feb 9, 2014
    Posts:
    65
    Hi, Im wanted to try new ECS and C# Jobs features and want to code simple collision system. I want to write job which will check Collider with all other Colliders and I dont know how to pass/inject array of all Colliders to job. Here is what I have so far

    Code (CSharp):
    1. namespace ECSGame
    2. {
    3.     [UsedImplicitly]
    4.     [UpdateAfter(typeof(RigidBodySystem))]
    5.     public class CollisionSystem : JobComponentSystem
    6.     {
    7.         [BurstCompile]
    8.         private struct UpdateBoundsJob : IJobProcessComponentData<Position, Collider>
    9.         {
    10.             public void Execute([ReadOnly] ref Position position, ref Collider collider)
    11.             {
    12.                 collider.Bounds.Center = position.Value + collider.Center;
    13.                 collider.Bounds.HalfWidth = collider.Size;
    14.             }
    15.         }
    16.  
    17.         [BurstCompile]
    18.         private struct CollisionJob : IJobProcessComponentData<Collider>
    19.         {
    20.             public void Execute([ReadOnly] ref Collider collider)
    21.             {
    22.                 foreach (var c in Colliders)
    23.                 {
    24.                     Check(collider.Bounds, c.Collider.Bounds);
    25.                 }
    26.             }
    27.  
    28.             private static bool Check(AABB a, AABB b)
    29.             {
    30.                 var x = math.abs(a.Center.x - b.Center.x) <= (a.HalfWidth.x + b.HalfWidth.x);
    31.                 var y = math.abs(a.Center.y - b.Center.y) <= (a.HalfWidth.y + b.HalfWidth.y);
    32.                 var z = math.abs(a.Center.z - b.Center.z) <= (a.HalfWidth.z + b.HalfWidth.z);
    33.  
    34.                 return x && y && z;
    35.             }
    36.         }
    37.  
    38.         protected override JobHandle OnUpdate(JobHandle inputDependencies)
    39.         {
    40.             var updateBoundsJob = new UpdateBoundsJob();
    41.             var updateBoundsJobHandle = updateBoundsJob.Schedule(this, inputDependencies);
    42.  
    43.             var collisionJob = new CollisionJob();
    44.             return collisionJob.Schedule(this, updateBoundsJobHandle);
    45.         }
    46.     }
    47. }
     
    Deleted User likes this.
  2. eizenhorn

    eizenhorn

    Joined:
    Oct 17, 2016
    Posts:
    2,683
    Colliders allowed only on main thread yet. Or it your own?
     
  3. Eldirfar

    Eldirfar

    Joined:
    Feb 9, 2014
    Posts:
    65
    It is my own entity. Im going pure ECS
     
    Deleted User likes this.
  4. Eldirfar

    Eldirfar

    Joined:
    Feb 9, 2014
    Posts:
    65
    Ok I came up with this
    Code (CSharp):
    1. using JetBrains.Annotations;
    2. using Unity.Burst;
    3. using Unity.Collections;
    4. using Unity.Entities;
    5. using Unity.Jobs;
    6. using Unity.Mathematics;
    7. using Unity.Transforms;
    8.  
    9. namespace ECSGame
    10. {
    11.     [UsedImplicitly]
    12.     [UpdateAfter(typeof(RigidBodySystem))]
    13.     public class CollisionSystem : JobComponentSystem
    14.     {
    15.         private struct Group
    16.         {
    17.             public readonly int Length;
    18.             public ComponentDataArray<Collider> Colliders;
    19.         }
    20.  
    21.         [BurstCompile]
    22.         private struct UpdateBoundsJob : IJobProcessComponentData<Position, Collider>
    23.         {
    24.             public void Execute([ReadOnly] ref Position position, ref Collider collider)
    25.             {
    26.                 collider.Bounds.Center = position.Value + collider.Center;
    27.                 collider.Bounds.HalfWidth = collider.Size;
    28.             }
    29.         }
    30.  
    31.         [BurstCompile]
    32.         private struct CollisionJob : IJobParallelFor
    33.         {
    34.             [ReadOnly] public ComponentDataArray<Collider> colliders;
    35.  
    36.             private static bool Check(AABB a, AABB b)
    37.             {
    38.                 var x = math.abs(a.Center.x - b.Center.x) <= (a.HalfWidth.x + b.HalfWidth.x);
    39.                 var y = math.abs(a.Center.y - b.Center.y) <= (a.HalfWidth.y + b.HalfWidth.y);
    40.                 var z = math.abs(a.Center.z - b.Center.z) <= (a.HalfWidth.z + b.HalfWidth.z);
    41.  
    42.                 return x && y && z;
    43.             }
    44.  
    45.             public void Execute(int index)
    46.             {
    47.                 for (var i = index + 1; i < colliders.Length; i++)
    48.                 {
    49.                     Check(colliders[index].Bounds, colliders[i].Bounds);
    50.                 }
    51.             }
    52.         }
    53.  
    54.         [Inject]
    55.         private Group group;
    56.  
    57.         protected override JobHandle OnUpdate(JobHandle inputDependencies)
    58.         {
    59.             var updateBoundsJob = new UpdateBoundsJob();
    60.             var updateBoundsJobHandle = updateBoundsJob.Schedule(this, inputDependencies);
    61.  
    62.             var collisionJob = new CollisionJob
    63.             {
    64.                 colliders = group.Colliders
    65.             };
    66.             return collisionJob.Schedule(group.Length, 100, updateBoundsJobHandle);
    67.         }
    68.     }
    69. }
    and it seems work. But checking collisions between 2000 entities costs 16ms and with 20000 entities editor freezes :D I think I will need another solution for such scale.
     
  5. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,759
    Just a heads up, injection like that will be removed soon~

    Also you need a broadphase to limit the number of checks you need to perform. Some type of spatial map etc.

    Usually you should only need to perform a couple of dozen checks at most for collisions.
     
  6. Eldirfar

    Eldirfar

    Joined:
    Feb 9, 2014
    Posts:
    65
    By removing method call in job i was able to get 50ms for 20000 entities and few second freez at hit play in editor. For sure will need some thing to reduce checks count.
     
  7. eizenhorn

    eizenhorn

    Joined:
    Oct 17, 2016
    Posts:
    2,683
    Octree or spatial map, direct check All<->All not use no one :)
     
  8. Eldirfar

    Eldirfar

    Joined:
    Feb 9, 2014
    Posts:
    65
    Ye, i know it's not the best solution. I just wanted to try simple solution and check how it will work with burst and c# jobs.
     
  9. Derebeyi

    Derebeyi

    Joined:
    Jun 3, 2015
    Posts:
    7
    Oh noes! I'm building on that. Do we know what will be the replacement and what is suggested to be used in meantime?
     
  10. eizenhorn

    eizenhorn

    Joined:
    Oct 17, 2016
    Posts:
    2,683
    Chunk Iteration and Component Groups.
     
  11. Derebeyi

    Derebeyi

    Joined:
    Jun 3, 2015
    Posts:
    7
    Component groups look cleaner,I'll stick with them.However you are more experienced than me,what do you suggest for performance?
     
  12. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,759
    The general approach now is to turn the component group into chunk iteration

    var chunks = this.chunkGroup.CreateArchetypeChunkArray(Allocator.TempJob);


    The alternative to chunk iteration, which is very clean and ideally should be used where possible is

    IJobProcessComponentData

    IJobProcessComponentDataWithEntity


    This does chunk iteration behind the scenes but hides it. Ever since the added the WithEntity version you should be able to do the majority of your work with it.

    The only thing that is currently limited with these 2 approaches seems to be hybrid/legacy objects.
     
    Last edited: Oct 31, 2018
  13. eizenhorn

    eizenhorn

    Joined:
    Oct 17, 2016
    Posts:
    2,683
    + IJobChunk
     
  14. eizenhorn

    eizenhorn

    Joined:
    Oct 17, 2016
    Posts:
    2,683
    Both.
     
  15. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,769
    I was a bit slacking in ECS area recently. Missed important news.
    What is current alternative for injection?
    Keywords, or reference to the related topic would be sufficient.
     
  16. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,769
    Ok, in meantime. found partial answer.