void DestroyBatch(Entity *entities, Chunk *chunk, int indexInChunk, int batchCount) { var archetype = chunk->Archetype; if (!archetype->SystemStateCleanupNeeded) { DeallocateDataEntitiesInChunk(entities, chunk, indexInChunk, batchCount); ManagedChangesTracker.IncrementComponentOrderVersion(archetype, chunk->SharedComponentValues); IncrementComponentTypeOrderVersion(archetype); if (chunk->ManagedArrayIndex >= 0) { // We can just chop-off the end, no need to copy anything if (chunk->Count != indexInChunk + batchCount) { ManagedChangesTracker.CopyManagedObjects(chunk, chunk->Count - batchCount, chunk, indexInChunk, batchCount); } ManagedChangesTracker.ClearManagedObjects(chunk, chunk->Count - batchCount, batchCount); } chunk->Archetype->EntityCount -= batchCount; SetChunkCount(chunk, chunk->Count - batchCount); } else { var dstArchetypeChunkFilter = new ArchetypeChunkFilter(); dstArchetypeChunkFilter.Archetype = archetype->SystemStateResidueArchetype; if (RequiresBuildingResidueSharedComponentIndices(archetype, dstArchetypeChunkFilter.Archetype)) { BuildResidueSharedComponentIndices(archetype, dstArchetypeChunkFilter.Archetype, chunk->SharedComponentValues, dstArchetypeChunkFilter.SharedComponentValues); } if (batchCount == chunk->Count) { Move(chunk, ref dstArchetypeChunkFilter); } else { Move(new EntityBatchInChunk { Chunk = chunk, StartIndex = indexInChunk, Count = batchCount }, ref dstArchetypeChunkFilter); } } }
// ---------------------------------------------------------------------------------------------------------- // Core, self-contained functions to change chunks. No other functions should actually move data from // one Chunk to another, or otherwise change the structure of a Chunk after creation. // ---------------------------------------------------------------------------------------------------------- /// <summary> /// Move subset of chunk data into another chunk. /// - Chunks can be of same archetype (but differ by shared component values) /// - Returns number moved. Caller handles if less than indicated in srcBatch. /// </summary> /// <returns></returns> int Move(EntityBatchInChunk srcBatch, Chunk *dstChunk) { var srcChunk = srcBatch.Chunk; var srcChunkIndex = srcBatch.StartIndex; var srcCount = srcBatch.Count; var srcArchetype = srcChunk->Archetype; var dstArchetype = dstChunk->Archetype; // Note (srcArchetype == dstArchetype) is valid // Archetypes can the the same, but chunks still differ because filter is different (e.g. shared component) int dstChunkIndex; var dstCount = AllocateIntoChunk(dstChunk, srcCount, out dstChunkIndex); // If can only move partial batch, move from the end so that remainder of batch isn't affected. srcChunkIndex = srcChunkIndex + srcCount - dstCount; ChunkDataUtility.Convert(srcChunk, srcChunkIndex, dstChunk, dstChunkIndex, dstCount); if (dstChunk->ManagedArrayIndex >= 0 && srcChunk->ManagedArrayIndex >= 0) { ManagedChangesTracker.CopyManagedObjects(srcChunk, srcChunkIndex, dstChunk, dstChunkIndex, dstCount); } var dstEntities = (Entity *)ChunkDataUtility.GetComponentDataRO(dstChunk, dstChunkIndex, 0); for (int i = 0; i < dstCount; i++) { var entity = dstEntities[i]; SetArchetype(entity, dstArchetype); SetEntityInChunk(entity, new EntityInChunk { Chunk = dstChunk, IndexInChunk = dstChunkIndex + i }); } // Fill in moved component data from the end. var srcTailIndex = srcChunkIndex + dstCount; var srcTailCount = srcChunk->Count - srcTailIndex; var fillCount = math.min(dstCount, srcTailCount); if (fillCount > 0) { var fillStartIndex = srcChunk->Count - fillCount; ChunkDataUtility.Copy(srcChunk, fillStartIndex, srcChunk, srcChunkIndex, fillCount); var fillEntities = (Entity *)ChunkDataUtility.GetComponentDataRO(srcChunk, srcChunkIndex, 0); for (int i = 0; i < fillCount; i++) { var entity = fillEntities[i]; SetEntityInChunk(entity, new EntityInChunk { Chunk = srcChunk, IndexInChunk = srcChunkIndex + i }); } if (srcChunk->ManagedArrayIndex >= 0) { ManagedChangesTracker.CopyManagedObjects(srcChunk, fillStartIndex, srcChunk, srcChunkIndex, fillCount); } } if (srcChunk->ManagedArrayIndex >= 0) { ManagedChangesTracker.ClearManagedObjects(srcChunk, srcChunk->Count - dstCount, dstCount); } srcArchetype->EntityCount -= dstCount; dstChunk->SetAllChangeVersions(GlobalSystemVersion); srcChunk->SetAllChangeVersions(GlobalSystemVersion); ManagedChangesTracker.IncrementComponentOrderVersion(srcArchetype, srcChunk->SharedComponentValues); IncrementComponentTypeOrderVersion(srcArchetype); ManagedChangesTracker.IncrementComponentOrderVersion(dstArchetype, dstChunk->SharedComponentValues); IncrementComponentTypeOrderVersion(dstArchetype); SetChunkCount(srcChunk, srcChunk->Count - dstCount); // Cannot DestroyEntities unless SystemStateCleanupComplete on the entity chunk. if (dstChunk->Archetype->SystemStateCleanupComplete) { DestroyEntities(dstEntities, dstCount); } return(dstCount); }
void DestroyBatch(Entity *entities, Chunk *chunk, int indexInChunk, int batchCount) { var archetype = chunk->Archetype; if (!archetype->SystemStateCleanupNeeded) { DeallocateDataEntitiesInChunk(entities, chunk, indexInChunk, batchCount); ManagedChangesTracker.IncrementComponentOrderVersion(archetype, chunk->SharedComponentValues); IncrementComponentTypeOrderVersion(archetype); if (chunk->ManagedArrayIndex >= 0) { // We can just chop-off the end, no need to copy anything if (chunk->Count != indexInChunk + batchCount) { ManagedChangesTracker.CopyManagedObjects(chunk, chunk->Count - batchCount, chunk, indexInChunk, batchCount); } ManagedChangesTracker.ClearManagedObjects(chunk, chunk->Count - batchCount, batchCount); } chunk->Archetype->EntityCount -= batchCount; SetChunkCount(chunk, chunk->Count - batchCount); } else { var newType = archetype->SystemStateResidueArchetype; var sharedComponentValues = chunk->SharedComponentValues; if (RequiresBuildingResidueSharedComponentIndices(archetype, newType)) { var tempAlloc = stackalloc int[newType->NumSharedComponents]; BuildResidueSharedComponentIndices(archetype, newType, sharedComponentValues, tempAlloc); sharedComponentValues = tempAlloc; } // See: https://github.com/Unity-Technologies/dots/issues/1387 // For Locked Order Chunks specfically, need to make sure that structural changes are always done per-chunk. // If trying to muutate structure in a way that is not per chunk, will hit an exception in the else clause anyway. // This ultimately needs to be replaced by entity batch interface. if (batchCount == chunk->Count) { ManagedChangesTracker.IncrementComponentOrderVersion(archetype, chunk->SharedComponentValues); IncrementComponentTypeOrderVersion(archetype); SetArchetype(chunk, newType, sharedComponentValues); } else { for (var i = 0; i < batchCount; i++) { var entity = entities[i]; ManagedChangesTracker.IncrementComponentOrderVersion(archetype, GetChunk(entity)->SharedComponentValues); IncrementComponentTypeOrderVersion(archetype); SetArchetype(entity, newType, sharedComponentValues); } } } }