How to Access an Entity’s Archetype in a Job?

I’m looking for good ways to access an entity’s archetype from inside a job. Not the archetype of the chunk I am currently working on, but ways to look up any entity’s archetype.

It would be nice if there was an ‘ArchetypeFromEntity’ structure, with similar performance to ComponentDataFromEntity.

But maybe there are ways to do something similar that I don’t know about. Thank you for any help!

It’s probably not what you want, but EntityQueryMask is a data type that allows you to check if an Entity belongs to a specific EntityQuery while in a job. Be careful, because you can only create 1024 masks and once you create a mask you can never destroy it again unless you destroy the world.

1 Like

Thanks for the reply! But as you figured, I’m looking to access the EntityArchetype value itself.

What is your use case for getting the archetype inside a job?

One use case is written here:

https://forum.unity.com/threads/request-an-improvement-to-entityarchetype.904907/

To summarize from that thread: I believe the process of making structural changes could be significantly more efficient. Right now, if you want to change an entity’s archetype, the common path is to queue several different structural changes by calling EntityCommandBuffer.Concurrent.Add/RemoveComponent(), once for each component type.

When the ECB is played back, these components will be added or removed in separate, individual steps. For each of those changes, an entity’s archetype changes, and its data must be copied to another chunk. If you add 5 different components using an ECB, then you end up copying that entity’s data 5 different times.

But in most cases, you’d only really care that the entity ends up in a chunk that contains the 5 component types that you wanted to add. This could be done with just a single structural change:

  1. From inside a job, get the entity’s current archetype.
  2. Calculate the new, target archetype that you’d like that entity to have (based on the current archetype, plus or minus the component types are want to add or remove).
  3. Add that entity, along with the target archetype, to a native collection like a NativeQueue.
  4. Back on the main thread, process that queue, and call EntityManager.SetArchetype(entity, targetArchetype) for each of the queued entries.

If you need to populate component data into one of the new types you just added, you can follow up immediately after step 4, with new jobs which populate that data.

Now, no matter how many component types you’d like to add or remove, the entity only ever undergoes one structural change.

I’m nervous to write out this idea, because I’m concerned it might be written off for being out of the norm. I believe that would be a mistake. At least on paper, it seems like this would objectively be a much more efficient way to make component changes to an entity. And you’d start seeing perf gains the moment you want to change more than one component type.

If the idea is to be discarded, it at least deserves an explanation of why it wouldn’t be more (potentially much more) efficient.


For what it’s worth, a better implementation would be to refactor EntityCommandBuffer, such that it does this type of batching automatically:

  1. As jobs queue ECB commands to add or remove components, they would get grouped inside the ECB, per entity.
  2. On playback, the ECB would do steps 1-4 (from the list above), figuring out a new target archetype for the entity, before copying it’s component data only once.
  3. Any ECB commands to set component data would then be played back after step 2, once all of these structural changes have been made (with determinism in mind).

^ I believe there was talk of something similar to this in the Q&A portion of this excellent talk from Unite Copenhagen 2019 (this embedded video is timestamped to that moment):

But what’s mentioned there is more about batching multiple instantiation commands (not structural changes to existing entities).


A good third approach would be a combination of these first two:

  1. Add something like ArchetypeFromEntity, to let us access an entity’s archetype from a job.
  2. Let us calculate the new target archetype in that same job.
  3. Add an EntityCommandBuffer.Concurrent.SetArchetype() function, which we could use to queue up the single structural change ourselves from inside the same job (no big ECB refactor required).
  4. Let the user continue to queue up data changes by calling EntityCommandBuffer.Concurrent.SetComponent() from inside that same job. Now determinism isn’t a concern - it’s handled the same way that is already is in ECBs.

If Unity wanted to address the inefficiency in any of these ways, that would be truly wonderful.

I was hesitant to ask for such a large refactor of ECB. A smaller lift like being able to find an entity’s archetype in a job would let us do the same thing ourselves.

2 Likes

Really what is missing is batch API for the following EntiyManager methods:

  • AddComponents
  • RemoveComponents
  • SetArchetype
  • SetEnabled
2 Likes

If any Unity devs have time to respond, I would truly appreciate it.

The idea I described in my previous post - am I right to think it would be more efficient that what DOTS offers now (in cases when you want to change more than one Component type)?

Thank you for any input.