here is a chunk with entities that have no components
how to query those poor fellows?
While you got valid question, I would ask first, how they happened?
You could create an EntityQuery that explicitly excludes all component types, but that’s brittle and would break if you forgot any component or someone else adds one. Alternatively, you could query the chunks themselves. This should do the trick, but I haven’t had the time to test it:
using(var chunks = EntityManager.GetAllChunks()) {
var bareEntity = EntityManager.GetEntityOnlyArchetype();
UnityEngine.Debug.Assert(bareEntity.GetComponentTypes().Length == 0);
for (int c = 0; c < chunks.Length; c++) {
if (chunks[c].Archetype == bareEntity) {
// do your thing here.
}
}
}
What’s the use of a completely empty entity?
they had components before, but all of them was removed at some point
this is a good question
yes, this is possible with chunk iteration, but is there a simple way?
I don’t know why but this whole conversation chain made me laugh out loud. Oh boy.
the problem of entities who lost everything isn’t a joke, this is a problem we need to solve together,
if you have nothing to say better to donate a few spare components, or used buffer elements in good condition going to be very helpful as well
@SubPixelPerfect was that component with data, or with tag?
For example, if I would have entity which suppose only to trigger some system, with single tag, or component, after job is done, remove entity, not the component.
I tend to remove tags, but not components with data. Or create short living entities, which will be removed soon after.
I avoid situation as fire, where entity become orphaned. Just thoughts.
To tell the truth this is not a real case, I’ve made it just out of curiosity to know if orphan get destroyed automatically. So the answer is they don’t, and it is not that obvious how to cleanup them. So here I totally agree - it is better to avoid situation like this.
Don’t know if is best option, but you could do checks, based on components count.
Simply check, if entities are 0 components. Of course you need iterate all entities in this case, or at least already filtered out entities.
EntityManager.GetComponentCount ( entity ) ;
The easiest way of getting rid of entities with no components is:
Entities.ForEach((Entity e) => {
if (EntityManager.GetComponentCount(e) == 0)
PostUpdateCommands.DestroyEntity(e);
});
Note that this generates garbage.
What if you have 100,000 components That’s a lot of iterations.
I feel like sschoener is on the right track and it’s easy to turn into a job.
Well. I didn’t say it was performant. But then again there shouldn’t be empty entities wondering around
I might be a little ignorant here, but what’re the odds this is a chunk with a SharedComponentData
still attached? It could even be some SystemSharedComponentData
that isn’t quite cleaned up.
Grabbing on what @sschoener wrote i’ve created a job for destroying empty entities:
[BurstCompile]
struct DestroyOnlyEntities : IJobChunk {
public EntityArchetype EntityOnlyArchetype;
[ReadOnly]
public ArchetypeChunkEntityType EntityType;
[WriteOnly]
public EntityCommandBuffer.Concurrent CmdBuffer;
public void Execute(ArchetypeChunk chunk, int chunkIndex, int firstEntityIndex) {
var entities = chunk.GetNativeArray(EntityType);
if (chunk.Archetype == EntityOnlyArchetype)
for (var i = 0; i < chunk.Count; i++)
CmdBuffer.DestroyEntity(firstEntityIndex + i, entities[i]);
}
}
When scheduling pass EntityManager.UniversalQuery as it’s query.
Note that it’s even burstable because EntityCommandBuffer.DestroyEntity is supported by Burst.
This solution doesn’t work anymore on Entities 0.2.0 because EntityManager.GetEntityOnlyArchetype() was removed.
Actually you can use EntityManager.CreateArchetype() which is the same as our old EntityManager.GetEntityOnlyArchetype().
So this works again