How to create a simple nested loop in Job System ?

Hi this is my first project with using ECS, i am currently creating a collision detection system for circle colliders, currently my code look like this:

public class CollisionSystem : JobComponentSystem
{
    [DeallocateOnJobCompletion]
    public NativeArray<CircleCollider> Colliders;

    [BurstCompile]
    struct CollisionJob : IJobParallelFor
    {
        [ReadOnly]
        [DeallocateOnJobCompletion]
        public NativeArray<CircleCollider> colliders;

        public void Execute(int index)
        {
            int size = colliders.Length;
            for(int j = 0; j < size; j++)
            {
                float3 pos = colliders[j].position;
                //collision detection
            }
        }
    }

    protected override JobHandle OnUpdate(JobHandle inputDeps)
    {
        Colliders = GetEntityQuery(typeof(CircleCollider)).ToComponentDataArray<CircleCollider>(Allocator.TempJob);

        var job = new CollisionJob()
        {
            colliders = Colliders
        };
        var jobHandle = job.Schedule(Colliders.Length, 64);
        return jobHandle;
    }
   
}

And i got some questions, why i got such low performance on that ? If i want to take a collider from the array i got low performance, but when the loop got no operations inside, everything is ok. How can i create such comparison mechanic by using jobs ?

Well unlike normal C#, Burst will aggressively optimize and completely skip loops if they aren’t necessary. So an empty internal loop is never run. Most likely whatever you are doing inside your inner loop is expensive.

A couple of quick pointers:
You probably want j to start at index + 1. Or you can sort the circles by x component minus radius to do a sweep and prune algorithm. If that is still too slow, you’ll need a more aggressive spatial partitioning technique.

Currently is just an simple nested loop for 25 thousand of colliders, in each loop i am just only grabbing the position like above.
It’s a bit awkward that such simple operation is generating such low performance.

that’s 625 million iterations…

Yeah i will rethink my collision detection in ECS.

1 Like

This is one of the areas where I think Unity needs multi-dimensional Native containers, then you could group the colliders into a 3d array and only have to check colliders in the same area and neighboring areas.

You could probably get around it with some kind of hashmap or conversion from 3d coordinates to linear system e.g. 10x10x10 grid with 000-999 where 3d coordinates are XYZ values.

1 Like