Is this the best practice?

Hi! I want to do something like this:

  1. I have 3 kinds of entities: garden, room and user.
  2. The gardens and rooms have components Position. The users have components Host(tells which room it belongs to) and NearbyGardenCount(records how many gardens are within certain distance).
  3. Now I want to update all NearbyGardenCount.

What i would do is :

  1. schedule a ijobentity to traverse through all rooms and record the (Entity, Position) with a NativeQueue
  2. force to complete the job and transfer the queue into a NativeHashMap<Entity, Position>
  3. schedule a ijobentity to traverse through all gardens and record the Position with a NativeQueue
  4. force to complete the job and transfer the queue into a NativeArray<Position>
  5. schedule a ijobentity to traverse through all users with the two native collectors passed in as [ReadOnly]. Get the room it belongs to, get its position and check the distance to every garden and update the NearbyGardenCount.

Is there a better way to do this?

Shouldn’t need to force complete the jobs to transfer data from the queue to other types, can schedule another job as a dependency of the prior job, and inside that job copy the data into into your nativearray/hashmap before scheduling the final job

2 Likes

Hi, thelebaron. Thanks for your reply!

if there a way to resize the capacity of the nativearray/hashmap in a job? or i need to initialize them with capacity big enough before passing them into the job?

Id use CalculateEntityCount() on the queries of rooms/gardens/users to predetermine your collection sizes, unless Rooms/Gardens doesnt directly correlate to the Entity/Position data.
At least with 3. and 4. you could just schedule one job using either ToComponentDataListAsync or ToComponentDataArray and just copy it directly to your nativearray. Actually reading through this again I would do this with 1 & 2 as well, and skip the nativequeue, unless theres more context to this than I am inferring from the post.

1 Like

Hi, thelebaron. If you used ToComponentDataListAsync/ToComponentDataArray for 1&2, how would you get the room for a user quickly? or is there a method to convert the component data into a nativehashmap?

I’m sort of unclear on the relationship between a user, host component and if they relate at all an entity or not. But in any case: NativeHashmap can be added to and resized inside a job(negating the need for queue job), and also for 3. you can simply add to a NativeList and use that NativeList.AsArray() when you need readonly for a subsequent job(again bypassing use of a queue).
There are tons of different ways to tackle this, and its always a bit of a challenge to mentally come up with ways to do so without seeing a bit more information.

The original way would work too, obviously not optimal(and also Im sure other users can chime in with more optimized ways of doing things than I suggested), but with dots even a “non optimal” route will be faster than a non dots solution, so go with what makes sense so far, and profile and see if it makes sense to keep optimizing.

1 Like

You don’t need step 1 and 3. You can collect the room and garden information and place them directly to NativeHashMap or a NativeList. If you want this to be multithreaded, you can use NativeHashMap.ParallelWriter and NativeList.ParallelWriter.

But in general, yes, this is how you code with DOTS (chaining jobs) but you should avoid completing jobs. Only do so if you really need the result right away like syncing with the managed world.

1 Like