Job.WithCode with EntityQuery?

Ok I know I am probably doing this completely wrong, but this is what I am TRYING to do in concept. But I can’t get it to work. Is there a different way I should be doing this, or am I on the right track but just have some syntax issues? I know this syntax I am using doesn’t work.

I have N number of entities with a float2 component on them. I want to get all of those entities and process them as ONE batch, not individual entities. I need the points from all of them to then generate data.

    public class GenerateVoronoiDiagramSystem : JobComponentSystem
    {
        protected override JobHandle OnUpdate(JobHandle inputDeps)
        {
            EntityQuery pointsQuery = GetEntityQuery(ComponentType.ReadOnly<PointElement>());
            JobHandle buildVoronoi = Job.WithCode(() =>
            {
            }).Schedule(pointsQuery, inputDeps);

            return buildVoronoi;
        }
    }

You can do

       var points = pointsQuery.ToComponentDataArray<Point>(Allocator.TempJob);

To get a nativearray of all your points and then process that.

2 Likes

Ah so something like this then?

    public class GenerateVoronoiDiagramSystem : JobComponentSystem
    {
        private VoronoiGenerator generator;
       
        protected override JobHandle OnUpdate(JobHandle inputDeps)
        {
            EntityQuery pointsQuery = GetEntityQuery(ComponentType.ReadOnly<PointData>());
            NativeArray<PointData> points = pointsQuery.ToComponentDataArray<PointData>(Allocator.TempJob);
            if (generator == null)
            {
                generator = new VoronoiGenerator(1000, 1000, 0, 10);
            }

            if (points.Length == 0) return default;
           
            JobHandle buildVoronoi = Job.WithCode(() =>
            {
                Vector2[] vPoints = new Vector2[points.Length];
                for (int i = 0; i < points.Length; i++)
                {
                    vPoints[i] = new Vector2(points[i].Value.x, points[i].Value.y);
                }
                generator.Generate(vPoints);
            }).Schedule(inputDeps);

            return buildVoronoi;
        }
    }

You can’t use managed arrays (Vector2[ ] vPoints = new Vector2[points.Length]; like that inside a job: https://docs.unity3d.com/Manual/JobSystemSafetySystem.html

If your voronoi generator requires managed arrays you need to run it on the main thread or rework it it to function within the restrictions of the job system.

The intention is this would run on the main thread (it doesn’t benefit from multithreading) and I’m trying to SLOWLY work myself over to ECS rather than jump completely in :slight_smile:

Unfortunately unless I completely rewrite the generator it currently uses standard managed arrays. Is there something I need to do to inform Unity this needs to run on the main thread?

OnUpdate is running on the main thread. Just get move anything you need to be on the main thread out of the Job.WithCode and into the normal function scope.

Also protip, instead of building the array of Vector2 manually you can do var vecs = points.Reinterpret<Vector2>().ToArray() to get a managed array of Vector2. Just be aware this only works as long as your Point components ONLY contain a float2 or a Vector2 or any type that sensibly converts to it.

I should also say you can also do

Job.WithCode(()=>
{
  // Code
}).Run(); // < Run instead of schedule

This will force it to run on the main thread with the benefits of Burst.