public void PoisonUnusedDataInAllChunks(EntityArchetype archetype, byte value) { Unity.Entities.EntityComponentStore.AssertValidArchetype(m_Manager.GetCheckedEntityDataAccess()->EntityComponentStore, archetype); for (var i = 0; i < archetype.Archetype->Chunks.Count; ++i) { var chunk = archetype.Archetype->Chunks[i]; ChunkDataUtility.MemsetUnusedChunkData(chunk, value); } }
public void MoveEntitiesFromInternalAll(EntityManager srcEntities, NativeArray <EntityRemapUtility.EntityRemapInfo> entityRemapping) { var srcAccess = srcEntities.GetCheckedEntityDataAccess(); var selfAccess = GetCheckedEntityDataAccess(); #if ENABLE_UNITY_COLLECTIONS_CHECKS if (srcEntities.m_EntityDataAccess == m_EntityDataAccess) { throw new ArgumentException("srcEntities must not be the same as this EntityManager."); } if (entityRemapping.Length < srcAccess->EntityComponentStore->EntitiesCapacity) { throw new ArgumentException("entityRemapping.Length isn't large enough, use srcEntities.CreateEntityRemapArray"); } if (!srcAccess->ManagedComponentStore.AllSharedComponentReferencesAreFromChunks(srcAccess->EntityComponentStore)) { throw new ArgumentException( "EntityManager.MoveEntitiesFrom failed - All ISharedComponentData references must be from EntityManager. (For example EntityQuery.SetFilter with a shared component type is not allowed during EntityManager.MoveEntitiesFrom)"); } #endif BeforeStructuralChange(); srcEntities.BeforeStructuralChange(); var archetypeChanges = selfAccess->EntityComponentStore->BeginArchetypeChangeTracking(); MoveChunksFromAll(entityRemapping, srcAccess->EntityComponentStore, srcAccess->ManagedComponentStore); selfAccess->EntityComponentStore->EndArchetypeChangeTracking(archetypeChanges, selfAccess->EntityQueryManager); }
public static Components GetComponents(EntityManager m, Entity e) { Components components = new Components(); components.entity = e; components.components = new List <object>(); if (!m.Exists(e)) { return(components); } #if UNITY_EDITOR components.name = m.GetName(e); components.components.Add(components.name); #endif var access = m.GetCheckedEntityDataAccess(); var ecs = access->EntityComponentStore; ecs->GetChunk(e, out var chunk, out var chunkIndex); if (chunk == null) { return(components); } var archetype = chunk->Archetype; var types = chunk->Archetype->TypesCount; for (var i = 0; i < types; ++i) { var componentType = chunk->Archetype->Types[i]; if (componentType.IsSharedComponent) { continue; } ref readonly var typeInfo = ref TypeManager.GetTypeInfo(componentType.TypeIndex);
/// <summary> /// Copies all entities from srcEntityManager and replaces all entities in this EntityManager /// </summary> /// <remarks> /// Guarantees that the chunk layout & order of the entities will match exactly, thus this method can be used for deterministic rollback. /// This feature is not complete and only supports a subset of the EntityManager features at the moment: /// * Currently it copies all SystemStateComponents (They should not be copied) /// * Currently does not support class based components /// </remarks> public void CopyAndReplaceEntitiesFrom(EntityManager srcEntityManager) { srcEntityManager.CompleteAllJobs(); CompleteAllJobs(); var srcAccess = srcEntityManager.GetCheckedEntityDataAccess(); var selfAccess = GetCheckedEntityDataAccess(); using (var srcChunks = srcAccess->ManagedEntityDataAccess.m_UniversalQueryWithChunks.CreateArchetypeChunkArrayAsync(Allocator.TempJob, out var srcChunksJob)) using (var dstChunks = selfAccess->ManagedEntityDataAccess.m_UniversalQueryWithChunks.CreateArchetypeChunkArrayAsync(Allocator.TempJob, out var dstChunksJob)) { using (var archetypeChunkChanges = EntityDiffer.GetArchetypeChunkChanges( srcChunks, dstChunks, Allocator.TempJob, jobHandle: out var archetypeChunkChangesJob, dependsOn: JobHandle.CombineDependencies(srcChunksJob, dstChunksJob))) { archetypeChunkChangesJob.Complete(); EntityDiffer.CopyAndReplaceChunks(srcEntityManager, this, selfAccess->ManagedEntityDataAccess.m_UniversalQueryWithChunks, archetypeChunkChanges); Unity.Entities.EntityComponentStore.AssertSameEntities(srcAccess->EntityComponentStore, selfAccess->EntityComponentStore); } } }
static void CloneAndAddChunks(EntityManager srcEntityManager, EntityManager dstEntityManager, NativeList <ArchetypeChunk> chunks) { var cloned = new NativeArray <ArchetypeChunk>(chunks.Length, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); var srcAccess = srcEntityManager.GetCheckedEntityDataAccess(); var dstAccess = dstEntityManager.GetCheckedEntityDataAccess(); for (var i = 0; i < chunks.Length; i++) { var srcChunk = chunks[i].m_Chunk; var dstChunk = CloneChunkWithoutAllocatingEntities( dstEntityManager, srcChunk, srcAccess->ManagedComponentStore); cloned[i] = new ArchetypeChunk { m_Chunk = dstChunk }; } // Ensure capacity in the dst world before we start linking entities. dstAccess->EntityComponentStore->EnsureCapacity(srcEntityManager.EntityCapacity); dstAccess->EntityComponentStore->CopyNextFreeEntityIndex(srcAccess->EntityComponentStore); new PatchAndAddClonedChunks { SrcChunks = chunks, DstChunks = cloned, DstEntityComponentStore = dstAccess->EntityComponentStore }.Schedule(chunks.Length, 64).Complete(); cloned.Dispose(); }
public InsideForEach(EntityManager manager) { m_Manager = manager; EntityDataAccess *g = manager.GetCheckedEntityDataAccess(); m_InsideForEachSafety = g->m_InsideForEach++; }
public void ReleaseUnusedBlobAssets() { using (var chunks = EntityManager.CreateEntityQuery(EntityGuidQueryDesc).CreateArchetypeChunkArray(Allocator.TempJob)) using (var blobAssets = EntityDiffer.GetBlobAssetsWithDistinctHash(EntityManager.GetCheckedEntityDataAccess()->ManagedComponentStore, chunks, Allocator.TempJob)) { m_BlobAssetBatchPtr->RemoveUnusedBlobAssets(blobAssets.BlobAssetsMap); } }
// Unsafe methods used to provide access for StructuralChanges public static unsafe T GetComponentData <T>(EntityManager manager, Entity entity, int typeIndex, out T originalComponent) where T : struct, IComponentData { var access = manager.GetCheckedEntityDataAccess(); var ecs = access->EntityComponentStore; UnsafeUtility.CopyPtrToStructure(ecs->GetComponentDataWithTypeRO(entity, typeIndex), out originalComponent); return(originalComponent); }
unsafe internal ArchetypeChunkComponentObjects(NativeArray <int> indexArray, EntityManager entityManager) { var access = entityManager.GetCheckedEntityDataAccess(); var ecs = access->EntityComponentStore; var mcs = access->ManagedComponentStore; m_IndexArray = indexArray; m_EntityComponentStore = ecs; m_ManagedComponentStore = mcs; }
public void Dispose() { EntityDataAccess *g = m_Manager.GetCheckedEntityDataAccess(); int newValue = --g->m_InsideForEach; if (m_InsideForEachSafety != newValue) { throw new InvalidOperationException("for each unbalanced"); } }
/// <summary> /// Gets the value of chunk component for the chunk containing the specified entity. /// </summary> /// <remarks> /// A chunk component is common to all entities in a chunk. You can access a chunk <see cref="IComponentData"/> /// instance through either the chunk itself or through an entity stored in that chunk. /// </remarks> /// <param name="entity">The entity.</param> /// <typeparam name="T">The component type.</typeparam> /// <returns>A struct of type T containing the component value.</returns> public static T GetChunkComponentData <T>(this EntityManager manager, Entity entity) where T : class, IComponentData { var ecs = manager.GetCheckedEntityDataAccess(); ecs->EntityComponentStore->AssertEntitiesExist(&entity, 1); var chunk = ecs->EntityComponentStore->GetChunk(entity); var metaChunkEntity = chunk->metaChunkEntity; return(ecs->GetComponentData <T>(metaChunkEntity, ecs->ManagedComponentStore)); }
static void DestroyChunks(EntityManager entityManager, NativeList <ArchetypeChunk> chunks) { var access = entityManager.GetCheckedEntityDataAccess(); var ecs = access->EntityComponentStore; for (var i = 0; i < chunks.Length; i++) { Assert.IsTrue(chunks[i].m_EntityComponentStore == access); DestroyChunkForDiffing(entityManager, chunks[i].m_Chunk); } }
static void ClearMissingReferences(EntityManager entityManager, NativeArray <ArchetypeChunk> chunks, out JobHandle jobHandle, JobHandle dependsOn) { jobHandle = new ClearMissingReferencesJob { TypeInfo = TypeManager.GetTypeInfoPointer(), EntityOffsetInfo = TypeManager.GetEntityOffsetsPointer(), GlobalSystemVersion = entityManager.GlobalSystemVersion, Chunks = chunks, EntityComponentStore = entityManager.GetCheckedEntityDataAccess()->EntityComponentStore, }.Schedule(chunks.Length, 64, dependsOn); }
public static unsafe T GetComponentObject <T>(this EntityManager entityManager, Entity entity) where T : Component { var access = entityManager.GetCheckedEntityDataAccess(); var ecs = access->EntityComponentStore; var mcs = access->ManagedComponentStore; var typeIndex = TypeManager.GetTypeIndex <T>(); var index = *access->GetManagedComponentIndex(entity, typeIndex); return((T)mcs.GetManagedComponent(index)); }
public static unsafe void WriteComponentData <T>(EntityManager manager, Entity entity, int typeIndex, ref T lambdaComponent, ref T originalComponent) where T : struct, IComponentData { var access = manager.GetCheckedEntityDataAccess(); var ecs = access->EntityComponentStore; // MemCmp check is necessary to ensure we only write-back the value if we changed it in the lambda (or a called function) if (UnsafeUtility.MemCmp(UnsafeUtility.AddressOf(ref lambdaComponent), UnsafeUtility.AddressOf(ref originalComponent), UnsafeUtility.SizeOf <T>()) != 0 && ecs->HasComponent(entity, typeIndex)) { UnsafeUtility.CopyStructureToPtr(ref lambdaComponent, ecs->GetComponentDataWithTypeRW(entity, typeIndex, ecs->GlobalSystemVersion)); } }
public static unsafe void Instantiate(this EntityManager entityManager, GameObject srcGameObject, NativeArray <Entity> outputEntities) { if (outputEntities.Length == 0) { return; } var entity = entityManager.Instantiate(srcGameObject); outputEntities[0] = entity; var entityPtr = (Entity *)outputEntities.GetUnsafePtr(); entityManager.GetCheckedEntityDataAccess()->InstantiateInternal(entity, entityPtr + 1, outputEntities.Length - 1); }
public void Execute() { var dstEntityComponentStore = DstEntityManager.GetCheckedEntityDataAccess()->EntityComponentStore; var remapping = new UnsafeHashMap <int, int>(SrcSharedComponentIndices.Length, Allocator.Temp); for (int i = 0; i < SrcSharedComponentIndices.Length; i++) { remapping.Add(SrcSharedComponentIndices[i], DstSharedComponentIndices[i]); } for (int i = 0; i < Chunks.Length; i++) { HandleChunk(i, dstEntityComponentStore, remapping); } }
static void DestroyChunks(EntityManager entityManager, NativeList <ArchetypeChunk> chunks) { s_DestroyChunksProfilerMarker.Begin(); new DestroyChunksJob { EntityManager = entityManager, Chunks = chunks }.Run(); s_PlaybackManagedChangesMarker.Begin(); var access = entityManager.GetCheckedEntityDataAccess(); var ecs = access->EntityComponentStore; var mcs = access->ManagedComponentStore; mcs.Playback(ref ecs->ManagedChangesTracker); s_PlaybackManagedChangesMarker.End(); s_DestroyChunksProfilerMarker.End(); }
public void Execute() { var access = EntityManager.GetCheckedEntityDataAccess(); var ecs = access->EntityComponentStore; for (var i = 0; i < Chunks.Length; i++) { var chunk = Chunks[i].m_Chunk; var count = chunk->Count; ChunkDataUtility.DeallocateBuffers(chunk); ecs->DeallocateManagedComponents(chunk, 0, count); chunk->Archetype->EntityCount -= chunk->Count; ecs->FreeEntities(chunk); ChunkDataUtility.SetChunkCountKeepMetaChunk(chunk, 0); } }
static void DestroyChunkForDiffing(EntityManager entityManager, Chunk *chunk) { var access = entityManager.GetCheckedEntityDataAccess(); var ecs = access->EntityComponentStore; var mcs = access->ManagedComponentStore; var count = chunk->Count; ChunkDataUtility.DeallocateBuffers(chunk); ecs->DeallocateManagedComponents(chunk, 0, count); chunk->Archetype->EntityCount -= chunk->Count; ecs->FreeEntities(chunk); ChunkDataUtility.SetChunkCountKeepMetaChunk(chunk, 0); mcs.Playback(ref ecs->ManagedChangesTracker); }
internal static void CopyAndReplaceChunks( EntityManager srcEntityManager, EntityManager dstEntityManager, EntityQuery dstEntityQuery, ArchetypeChunkChanges archetypeChunkChanges) { s_CopyAndReplaceChunksProfilerMarker.Begin(); var dstAccess = dstEntityManager.GetCheckedEntityDataAccess(); var srcAccess = srcEntityManager.GetCheckedEntityDataAccess(); var archetypeChanges = dstAccess->EntityComponentStore->BeginArchetypeChangeTracking(); DestroyChunks(dstEntityManager, archetypeChunkChanges.DestroyedDstChunks.Chunks); CloneAndAddChunks(srcEntityManager, dstEntityManager, archetypeChunkChanges.CreatedSrcChunks.Chunks); dstAccess->EntityComponentStore->EndArchetypeChangeTracking(archetypeChanges, dstAccess->EntityQueryManager); srcAccess->EntityComponentStore->InvalidateChunkListCacheForChangedArchetypes(); dstAccess->EntityComponentStore->InvalidateChunkListCacheForChangedArchetypes(); //@TODO-opt: use a query that searches for all chunks that have chunk components on it //@TODO-opt: Move this into a job // Any chunk might have been recreated, so the ChunkHeader might be invalid using (var allDstChunks = dstEntityQuery.CreateArchetypeChunkArray(Allocator.TempJob)) { foreach (var chunk in allDstChunks) { var metaEntity = chunk.m_Chunk->metaChunkEntity; if (metaEntity != Entity.Null) { if (dstEntityManager.Exists(metaEntity)) { dstEntityManager.SetComponentData(metaEntity, new ChunkHeader { ArchetypeChunk = chunk }); } } } } srcAccess->EntityComponentStore->IncrementGlobalSystemVersion(); dstAccess->EntityComponentStore->IncrementGlobalSystemVersion(); s_CopyAndReplaceChunksProfilerMarker.End(); }
// ---------------------------------------------------------------------------------------------------------- // INTERNAL // ---------------------------------------------------------------------------------------------------------- void MoveEntitiesFromInternalQuery(EntityManager srcEntities, EntityQuery filter, NativeArray <EntityRemapUtility.EntityRemapInfo> entityRemapping) { var srcAccess = srcEntities.GetCheckedEntityDataAccess(); var selfAccess = GetCheckedEntityDataAccess(); #if ENABLE_UNITY_COLLECTIONS_CHECKS if (filter._GetImpl()->_Access != srcAccess) { throw new ArgumentException( "EntityManager.MoveEntitiesFrom failed - srcEntities and filter must belong to the same World)"); } if (srcEntities.m_EntityDataAccess == m_EntityDataAccess) { throw new ArgumentException("srcEntities must not be the same as this EntityManager."); } #endif BeforeStructuralChange(); srcEntities.BeforeStructuralChange(); using (var chunks = filter.CreateArchetypeChunkArray(Allocator.TempJob)) { #if ENABLE_UNITY_COLLECTIONS_CHECKS for (int i = 0; i < chunks.Length; ++i) { if (chunks[i].m_Chunk->Archetype->HasChunkHeader) { throw new ArgumentException("MoveEntitiesFrom can not move chunks that contain ChunkHeader components."); } } #endif var archetypeChanges = selfAccess->EntityComponentStore->BeginArchetypeChangeTracking(); MoveChunksFromFiltered(chunks, entityRemapping, srcAccess->EntityComponentStore, srcAccess->ManagedComponentStore); selfAccess->EntityComponentStore->EndArchetypeChangeTracking(archetypeChanges, selfAccess->EntityQueryManager); selfAccess->EntityComponentStore->InvalidateChunkListCacheForChangedArchetypes(); srcAccess->EntityComponentStore->InvalidateChunkListCacheForChangedArchetypes(); } }
public static Components GetComponents(EntityManager m, Entity e) { Components components = new Components(); components.entity = e; components.components = new List <object>(); if (!m.Exists(e)) { return(components); } #if UNITY_EDITOR components.name = m.GetName(e); components.components.Add(components.name); #endif var access = m.GetCheckedEntityDataAccess(); var ecs = access->EntityComponentStore; ecs->GetChunk(e, out var chunk, out var chunkIndex); if (chunk == null) { return(components); } var archetype = chunk->Archetype; var types = chunk->Archetype->TypesCount; for (var i = 0; i < types; ++i) { var componentType = chunk->Archetype->Types[i]; if (componentType.IsSharedComponent) { continue; } var typeInfo = TypeManager.GetTypeInfo(componentType.TypeIndex); var type = TypeManager.GetType(typeInfo.TypeIndex); var offset = archetype->Offsets[i]; var size = archetype->SizeOfs[i]; var pointer = chunk->Buffer + (offset + size * chunkIndex); components.components.Add(GetComponent(pointer, type)); } return(components); }
internal unsafe override int InsertSharedComponent(EntityManager manager) { return(manager.GetCheckedEntityDataAccess()->ManagedComponentStore.InsertSharedComponent(m_SerializedData)); }
internal unsafe override void UpdateSerializedData(EntityManager manager, int sharedComponentIndex) { m_SerializedData = manager.GetCheckedEntityDataAccess()->ManagedComponentStore.GetSharedComponentData <T>(sharedComponentIndex); }
static void CloneAndAddChunks(EntityManager srcEntityManager, EntityManager dstEntityManager, NativeList <ArchetypeChunk> chunks) { s_CloneAndAddChunksProfilerMarker.Begin(); // sort chunks by archetype and clone chunks var srcSharedComponentIndices = new NativeList <int>(128, Allocator.TempJob); new CollectSharedComponentIndices { Chunks = chunks, SharedComponentIndices = srcSharedComponentIndices, }.Run(); // copy shared components s_CopySharedComponentsMarker.Begin(); var srcAccess = srcEntityManager.GetCheckedEntityDataAccess(); var dstAccess = dstEntityManager.GetCheckedEntityDataAccess(); var srcManagedComponentStore = srcAccess->ManagedComponentStore; var dstManagedComponentStore = dstAccess->ManagedComponentStore; var dstSharedComponentIndicesRemapped = new NativeArray <int>(srcSharedComponentIndices, Allocator.TempJob); dstManagedComponentStore.CopySharedComponents(srcManagedComponentStore, (int *)dstSharedComponentIndicesRemapped.GetUnsafeReadOnlyPtr(), dstSharedComponentIndicesRemapped.Length); s_CopySharedComponentsMarker.End(); // clone chunks var cloned = new NativeArray <ArchetypeChunk>(chunks.Length, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); new CreateNewChunks { Chunks = chunks, ClonedChunks = cloned, DstEntityManager = dstEntityManager, SrcSharedComponentIndices = srcSharedComponentIndices, DstSharedComponentIndices = dstSharedComponentIndicesRemapped, }.Run(); var copyJob = new CopyChunkBuffers { Chunks = chunks, ClonedChunks = cloned }.Schedule(chunks.Length, default); JobHandle.ScheduleBatchedJobs(); srcSharedComponentIndices.Dispose(); s_PlaybackManagedChangesMarker.Begin(); dstManagedComponentStore.Playback(ref dstAccess->EntityComponentStore->ManagedChangesTracker); // Release any references obtained by CopySharedComponents above for (var i = 0; i < dstSharedComponentIndicesRemapped.Length; i++) { dstAccess->RemoveSharedComponentReference(dstSharedComponentIndicesRemapped[i]); } s_PlaybackManagedChangesMarker.End(); dstSharedComponentIndicesRemapped.Dispose(); copyJob.Complete(); s_CopyManagedComponentsMarker.Begin(); for (int i = 0; i < cloned.Length; i++) { var dstChunk = cloned[i].m_Chunk; var dstArchetype = dstChunk->Archetype; var numManagedComponents = dstArchetype->NumManagedComponents; var hasHybridComponents = dstArchetype->HasHybridComponents; for (int t = 0; t < numManagedComponents; ++t) { int indexInArchetype = t + dstChunk->Archetype->FirstManagedComponent; var offset = dstChunk->Archetype->Offsets[indexInArchetype]; var a = (int *)(dstChunk->Buffer + offset); int count = dstChunk->Count; if (hasHybridComponents) { // We consider hybrid components as always different, there's no reason to clone those at this point. var typeCategory = TypeManager.GetTypeInfo(dstChunk->Archetype->Types[indexInArchetype].TypeIndex).Category; if (typeCategory == TypeManager.TypeCategory.UnityEngineObject) { // We still need to patch their indices, because otherwise they might point to invalid memory in // the managed component store. Setting them to the invalid index 0 is harmless, assuming nobody // actually operates on the shadow world. UnsafeUtility.MemSet(a, 0, sizeof(int) * count); continue; } } dstManagedComponentStore.CloneManagedComponentsFromDifferentWorld(a, count, srcManagedComponentStore, ref *dstAccess->EntityComponentStore); } } s_CopyManagedComponentsMarker.End(); // Ensure capacity in the dst world before we start linking entities. dstAccess->EntityComponentStore->EnsureCapacity(srcEntityManager.EntityCapacity); dstAccess->EntityComponentStore->CopyNextFreeEntityIndex(srcAccess->EntityComponentStore); new PatchAndAddClonedChunks { SrcChunks = chunks, DstChunks = cloned, DstEntityComponentStore = dstAccess->EntityComponentStore }.Schedule(chunks.Length, 64).Complete(); cloned.Dispose(); s_CloneAndAddChunksProfilerMarker.End(); }
static Chunk *CloneChunkWithoutAllocatingEntities(EntityManager dstEntityManager, Chunk *srcChunk, ManagedComponentStore srcManagedComponentStore) { var dstAccess = dstEntityManager.GetCheckedEntityDataAccess(); var dstEntityComponentStore = dstAccess->EntityComponentStore; var dstManagedComponentStore = dstAccess->ManagedComponentStore; // Copy shared component data var dstSharedIndices = stackalloc int[srcChunk->Archetype->NumSharedComponents]; srcChunk->SharedComponentValues.CopyTo(dstSharedIndices, 0, srcChunk->Archetype->NumSharedComponents); dstManagedComponentStore.CopySharedComponents(srcManagedComponentStore, dstSharedIndices, srcChunk->Archetype->NumSharedComponents); // @TODO: Why don't we memcpy the whole chunk. So we include all extra fields??? // Allocate a new chunk var srcArchetype = srcChunk->Archetype; var dstArchetype = dstEntityComponentStore->GetOrCreateArchetype(srcArchetype->Types, srcArchetype->TypesCount); var dstChunk = dstEntityComponentStore->GetCleanChunkNoMetaChunk(dstArchetype, dstSharedIndices); dstManagedComponentStore.Playback(ref dstEntityComponentStore->ManagedChangesTracker); dstChunk->metaChunkEntity = srcChunk->metaChunkEntity; // Release any references obtained by GetCleanChunk & CopySharedComponents for (var i = 0; i < srcChunk->Archetype->NumSharedComponents; i++) { dstManagedComponentStore.RemoveReference(dstSharedIndices[i]); } ChunkDataUtility.SetChunkCountKeepMetaChunk(dstChunk, srcChunk->Count); dstManagedComponentStore.Playback(ref dstEntityComponentStore->ManagedChangesTracker); dstChunk->Archetype->EntityCount += srcChunk->Count; var copySize = Chunk.GetChunkBufferSize(); UnsafeUtility.MemCpy((byte *)dstChunk + Chunk.kBufferOffset, (byte *)srcChunk + Chunk.kBufferOffset, copySize); var numManagedComponents = dstChunk->Archetype->NumManagedComponents; var hasHybridComponents = dstArchetype->HasHybridComponents; for (int t = 0; t < numManagedComponents; ++t) { int indexInArchetype = t + dstChunk->Archetype->FirstManagedComponent; if (hasHybridComponents) { // We consider hybrid components as always different, there's no reason to clone those at this point var typeCategory = TypeManager.GetTypeInfo(dstChunk->Archetype->Types[indexInArchetype].TypeIndex).Category; if (typeCategory == TypeManager.TypeCategory.Class) { continue; } } var offset = dstChunk->Archetype->Offsets[indexInArchetype]; var a = (int *)(dstChunk->Buffer + offset); dstManagedComponentStore.CloneManagedComponentsFromDifferentWorld(a, dstChunk->Count, srcManagedComponentStore, ref *dstAccess->EntityComponentStore); } BufferHeader.PatchAfterCloningChunk(dstChunk); dstChunk->SequenceNumber = srcChunk->SequenceNumber; return(dstChunk); }
/// <summary> /// Generates a detailed change set between <see cref="srcEntityManager"/> and <see cref="dstEntityManager"/>. /// All entities to be considered must have the <see cref="EntityGuid"/> component with a unique value. /// The resulting <see cref="Entities.EntityChanges"/> must be disposed when no longer needed. /// </summary> /// <remarks> /// When using the <see cref="EntityManagerDifferOptions.FastForwardShadowWorld"/> the destination world must be a direct ancestor to /// the source world, and must only be updated using this call or similar methods. There should be no direct changes to destination world. /// </remarks> internal static EntityChanges GetChanges( EntityManager srcEntityManager, EntityManager dstEntityManager, EntityManagerDifferOptions options, EntityQueryDesc entityQueryDesc, BlobAssetCache blobAssetCache, Allocator allocator) { s_GetChangesProfilerMarker.Begin(); CheckEntityGuidComponent(entityQueryDesc); var changes = default(EntityChanges); if (options == EntityManagerDifferOptions.None) { return(changes); } srcEntityManager.CompleteAllJobs(); dstEntityManager.CompleteAllJobs(); var srcEntityQuery = srcEntityManager.CreateEntityQuery(entityQueryDesc); var dstEntityQuery = dstEntityManager.CreateEntityQuery(entityQueryDesc); // Gather a set of a chunks to consider for diffing in both the src and dst worlds. using (var srcChunks = srcEntityQuery.CreateArchetypeChunkArrayAsync(Allocator.TempJob, out var srcChunksJob)) using (var dstChunks = dstEntityQuery.CreateArchetypeChunkArrayAsync(Allocator.TempJob, out var dstChunksJob)) { JobHandle clearMissingReferencesJob = default; if (CheckOption(options, EntityManagerDifferOptions.ClearMissingReferences)) { // Opt-in feature. // This is a special user case for references to destroyed entities. // If entity is destroyed, any references to that entity will remain set but become invalid (i.e. broken). // This option ensures that references to non-existent entities will be explicitly set to Entity.Null which // will force it to be picked up in the change set. ClearMissingReferences(srcEntityManager, srcChunks, out clearMissingReferencesJob, srcChunksJob); } var archetypeChunkChangesJobDependencies = JobHandle.CombineDependencies(srcChunksJob, dstChunksJob, clearMissingReferencesJob); // Broad phased chunk comparison. using (var archetypeChunkChanges = GetArchetypeChunkChanges( srcChunks: srcChunks, dstChunks: dstChunks, allocator: Allocator.TempJob, jobHandle: out var archetypeChunkChangesJob, dependsOn: archetypeChunkChangesJobDependencies)) { // Explicitly sync at this point to parallelize subsequent jobs by chunk. archetypeChunkChangesJob.Complete(); // Gather a sorted set of entities based on which chunks have changes. using (var srcEntities = GetSortedEntitiesInChunk( archetypeChunkChanges.CreatedSrcChunks, Allocator.TempJob, jobHandle: out var srcEntitiesJob)) using (var dstEntities = GetSortedEntitiesInChunk( archetypeChunkChanges.DestroyedDstChunks, Allocator.TempJob, jobHandle: out var dstEntitiesJob)) using (var srcBlobAssetsWithDistinctHash = GetBlobAssetsWithDistinctHash( srcEntityManager.GetCheckedEntityDataAccess()->ManagedComponentStore, srcChunks, Allocator.TempJob)) using (var dstBlobAssetsWithDistinctHash = blobAssetCache.BlobAssetBatch->ToNativeList(Allocator.TempJob)) { var duplicateEntityGuids = default(NativeList <DuplicateEntityGuid>); var forwardEntityChanges = default(EntityInChunkChanges); var reverseEntityChanges = default(EntityInChunkChanges); var forwardComponentChanges = default(ComponentChanges); var reverseComponentChanges = default(ComponentChanges); var forwardBlobAssetChanges = default(BlobAssetChanges); var reverseBlobAssetChanges = default(BlobAssetChanges); try { JobHandle getDuplicateEntityGuidsJob = default; JobHandle forwardChangesJob = default; JobHandle reverseChangesJob = default; if (CheckOption(options, EntityManagerDifferOptions.ValidateUniqueEntityGuid)) { // Guid validation will happen incrementally and only consider changed entities in the source world. duplicateEntityGuids = GetDuplicateEntityGuids( srcEntities, Allocator.TempJob, jobHandle: out getDuplicateEntityGuidsJob, dependsOn: srcEntitiesJob); } if (CheckOption(options, EntityManagerDifferOptions.IncludeForwardChangeSet)) { forwardEntityChanges = GetEntityInChunkChanges( srcEntityManager, dstEntityManager, srcEntities, dstEntities, Allocator.TempJob, jobHandle: out var forwardEntityChangesJob, dependsOn: JobHandle.CombineDependencies(srcEntitiesJob, dstEntitiesJob)); forwardComponentChanges = GetComponentChanges( forwardEntityChanges,
/// <summary> /// Gets the value of a component for an entity. /// </summary> /// <param name="entity">The entity.</param> /// <typeparam name="T">The type of component to retrieve.</typeparam> /// <returns>A struct of type T containing the component value.</returns> /// <exception cref="ArgumentException">Thrown if the component type has no fields.</exception> public static T GetComponentData <T>(this EntityManager manager, Entity entity) where T : class, IComponentData { var ecs = manager.GetCheckedEntityDataAccess(); return(ecs->GetComponentData <T>(entity, ecs->ManagedComponentStore)); }