// ---------------------------------------------------------------------------------------------------------- // INTERNAL // ---------------------------------------------------------------------------------------------------------- void MoveEntitiesFrom(out NativeArray <Entity> output, EntityManager srcEntities, NativeArray <ArchetypeChunk> chunks, NativeArray <EntityRemapUtility.EntityRemapInfo> entityRemapping) { #if ENABLE_UNITY_COLLECTIONS_CHECKS if (srcEntities == this) { throw new ArgumentException("srcEntities must not be the same as this EntityManager."); } 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 BeforeStructuralChange(); srcEntities.BeforeStructuralChange(); var archetypeChanges = EntityComponentStore->BeginArchetypeChangeTracking(); EntityManagerMoveEntitiesUtility.MoveChunks(chunks, entityRemapping, srcEntities.EntityComponentStore, srcEntities.ManagedComponentStore, EntityComponentStore, ManagedComponentStore); var changedArchetypes = EntityComponentStore->EndArchetypeChangeTracking(archetypeChanges); EntityGroupManager.AddAdditionalArchetypes(changedArchetypes); EntityRemapUtility.GetTargets(out output, entityRemapping); }
// ---------------------------------------------------------------------------------------------------------- // PUBLIC // ---------------------------------------------------------------------------------------------------------- /// <summary> /// Moves all entities managed by the specified EntityManager to the <see cref="World"/> of this EntityManager and fills /// an array with their <see cref="Entity"/> objects. /// </summary> /// <remarks> /// After the move, the entities are managed by this EntityManager. Use the `output` array to make post-move /// changes to the transferred entities. /// /// Each world has one EntityManager, which manages all the entities in that world. This function /// allows you to transfer entities from one World to another. /// /// **Important:** This function creates a sync point, which means that the EntityManager waits for all /// currently running Jobs to complete before moving the entities and no additional Jobs can start before /// the function is finished. A sync point can cause a drop in performance because the ECS framework may not /// be able to make use of the processing power of all available cores. /// </remarks> /// <param name="output">An array to receive the Entity objects of the transferred entities.</param> /// <param name="srcEntities">The EntityManager whose entities are appropriated.</param> /// <param name="entityRemapping">A set of entity transformations to make during the transfer.</param> /// <exception cref="ArgumentException"></exception> public void MoveEntitiesFrom(out NativeArray <Entity> output, EntityManager srcEntities, NativeArray <EntityRemapUtility.EntityRemapInfo> entityRemapping) { #if ENABLE_UNITY_COLLECTIONS_CHECKS if (srcEntities == this) { throw new ArgumentException("srcEntities must not be the same as this EntityManager."); } if (!srcEntities.m_ManagedComponentStore.AllSharedComponentReferencesAreFromChunks(srcEntities .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 = EntityComponentStore->BeginArchetypeChangeTracking(); EntityManagerMoveEntitiesUtility.MoveChunks(entityRemapping, srcEntities.EntityComponentStore, srcEntities.ManagedComponentStore, EntityComponentStore, ManagedComponentStore); EntityRemapUtility.GetTargets(out output, entityRemapping); var changedArchetypes = EntityComponentStore->EndArchetypeChangeTracking(archetypeChanges); EntityGroupManager.AddAdditionalArchetypes(changedArchetypes); //@TODO: Need to increment the component versions based the moved chunks... }
public static void Initialize() { if (s_Types != null) { return; } ObjectOffset = UnsafeUtility.SizeOf <ObjectOffsetType>(); #if !UNITY_CSHARP_TINY s_CreateTypeLock = new SpinLock(); s_ManagedTypeToIndex = new Dictionary <Type, int>(1000); #endif s_Types = new TypeInfo[MaximumTypesCount]; #if !UNITY_CSHARP_TINY s_StableTypeHashToTypeIndex = new Dictionary <ulong, int>(); #endif s_Count = 0; #if !UNITY_CSHARP_TINY s_Types[s_Count++] = new TypeInfo(null, 0, 0, TypeCategory.ComponentData, FastEquality.TypeInfo.Null, null, null, 0, -1, 0, 1, 0, null, 0, int.MaxValue); // This must always be first so that Entity is always index 0 in the archetype AddTypeInfoToTables(new TypeInfo(typeof(Entity), 1, sizeof(Entity), TypeCategory.EntityData, FastEquality.CreateTypeInfo <Entity>(), EntityRemapUtility.CalculateEntityOffsets <Entity>(), null, 0, -1, sizeof(Entity), UnsafeUtility.AlignOf <Entity>(), CalculateStableTypeHash(typeof(Entity)), null, 0, int.MaxValue)); InitializeAllComponentTypes(); #else StaticTypeRegistry.StaticTypeRegistry.RegisterStaticTypes(); #endif }
internal static object CloneAndPatchManagedComponent(object obj, EntityRemapUtility.EntityRemapInfo *remapping) { var clone = CloneManagedComponent(obj); EntityRemapUtility.PatchEntityInBoxedType(clone, remapping); return(clone); }
public void Execute(int index) { Chunk * chunk = remapChunks[index].chunk; Archetype *dstArchetype = remapChunks[index].dstArchetype; dstEntityComponentStore->RemapChunk(dstArchetype, chunk, 0, chunk->Count, ref entityRemapping); EntityRemapUtility.PatchEntities(dstArchetype->ScalarEntityPatches + 1, dstArchetype->ScalarEntityPatchCount - 1, dstArchetype->BufferEntityPatches, dstArchetype->BufferEntityPatchCount, chunk->Buffer, chunk->Count, ref entityRemapping); // Fix up chunk pointers in ChunkHeaders if (dstArchetype->HasChunkComponents) { var metaArchetype = dstArchetype->MetaChunkArchetype; var indexInTypeArray = ChunkDataUtility.GetIndexInTypeArray(metaArchetype, chunkHeaderType); var offset = metaArchetype->Offsets[indexInTypeArray]; var sizeOf = sizeof(ChunkHeader); // Set chunk header without bumping change versions since they are zeroed when processing meta chunk // modifying them here would be a race condition var metaChunkEntity = chunk->metaChunkEntity; var metaEntityInChunk = dstEntityComponentStore->GetEntityInChunk(metaChunkEntity); var chunkHeader = (ChunkHeader *)(metaEntityInChunk.Chunk->Buffer + (offset + sizeOf * metaEntityInChunk.IndexInChunk)); chunkHeader->ArchetypeChunk = new ArchetypeChunk(chunk, dstEntityComponentStore); } }
/// <summary> /// Invoked for each <see cref="Entity"/> member encountered. /// </summary> /// <param name="property">The property being visited.</param> /// <param name="container">The source container.</param> /// <param name="value">The entity value.</param> /// <typeparam name="TContainer">The container type.</typeparam> /// <returns>The status of the adapter visit.</returns> VisitStatus IVisit <Entity> .Visit <TContainer>(Property <TContainer, Entity> property, ref TContainer container, ref Entity value) { value = null != m_Info ? EntityRemapUtility.RemapEntity(m_Info, value) : EntityRemapUtility.RemapEntityForPrefab(m_PrefabSrc, m_PrefabDst, m_PrefabCount, value); return(VisitStatus.Stop); }
/// <summary> /// Moves all entities managed by the specified EntityManager to the <see cref="World"/> of this EntityManager and fills /// an array with their Entity objects. /// </summary> /// <remarks> /// After the move, the entities are managed by this EntityManager. Use the `output` array to make post-move /// changes to the transferred entities. /// /// Each world has one EntityManager, which manages all the entities in that world. This function /// allows you to transfer entities from one World to another. /// /// **Important:** This function creates a sync point, which means that the EntityManager waits for all /// currently running Jobs to complete before moving the entities and no additional Jobs can start before /// the function is finished. A sync point can cause a drop in performance because the ECS framework may not /// be able to make use of the processing power of all available cores. /// </remarks> /// <param name="output">An array to receive the Entity objects of the transferred entities.</param> /// <param name="srcEntities">The EntityManager whose entities are appropriated.</param> public void MoveEntitiesFrom(out NativeArray <Entity> output, EntityManager srcEntities) { using (var entityRemapping = srcEntities.CreateEntityRemapArray(Allocator.TempJob)) { MoveEntitiesFromInternalAll(srcEntities, entityRemapping); EntityRemapUtility.GetTargets(out output, entityRemapping); } }
public void Execute(int index) { Chunk * chunk = remapChunks[index].chunk; Archetype *dstArchetype = remapChunks[index].dstArchetype; dstEntityComponentStore->RemapChunk(dstArchetype, chunk, 0, chunk->Count, ref entityRemapping); EntityRemapUtility.PatchEntities(dstArchetype->ScalarEntityPatches + 1, dstArchetype->ScalarEntityPatchCount - 1, dstArchetype->BufferEntityPatches, dstArchetype->BufferEntityPatchCount, chunk->Buffer, chunk->Count, ref entityRemapping); }
public void Execute(int index) { Chunk * chunk = remapChunks[index].chunk; Archetype *dstArchetype = remapChunks[index].dstArchetype; dstEntityComponentStore->RemapChunk(dstArchetype, chunk, 0, chunk->Count, ref entityRemapping); EntityRemapUtility.PatchEntities(dstArchetype->ScalarEntityPatches + 1, dstArchetype->ScalarEntityPatchCount - 1, dstArchetype->BufferEntityPatches, dstArchetype->BufferEntityPatchCount, chunk->Buffer, chunk->Count, ref entityRemapping); chunk->Archetype = dstArchetype; chunk->ListIndex += dstArchetype->Chunks.Count; chunk->ListWithEmptySlotsIndex += dstArchetype->ChunksWithEmptySlots.Length; }
public void Execute(int index) { Chunk * chunk = remapChunks[index].chunk; Archetype *dstArchetype = remapChunks[index].dstArchetype; dstEntityDataManager->RemapChunk(dstArchetype, chunk, 0, chunk->Count, ref entityRemapping); EntityRemapUtility.PatchEntities(dstArchetype->ScalarEntityPatches + 1, dstArchetype->ScalarEntityPatchCount - 1, dstArchetype->BufferEntityPatches, dstArchetype->BufferEntityPatchCount, chunk->Buffer, chunk->Count, ref entityRemapping); chunk->Archetype = dstArchetype; for (int i = 0; i < dstArchetype->NumSharedComponents; ++i) { var componentIndex = chunk->SharedComponentValueArray[i]; componentIndex = remapShared[componentIndex]; chunk->SharedComponentValueArray[i] = componentIndex; } }
void PatchEntitiesForPrefab(int *managedComponents, int numManagedComponents, int allocatedCount, int remappingCount, Entity *remapSrc, Entity *remapDst) { #if !NET_DOTS for (int i = 0; i < allocatedCount; ++i) { for (int c = 0; c < numManagedComponents; c++) { var managedComponentIndex = managedComponents[c]; if (managedComponentIndex != 0) { var obj = m_ManagedComponentData[managedComponentIndex]; EntityRemapUtility.PatchEntityForPrefabInBoxedType(obj, remapSrc, remapDst, remappingCount); } } managedComponents += numManagedComponents; remapDst += remappingCount; } #endif }
public void PatchEntities(ManagedComponentStore managedComponentStore, Archetype *archetype, Chunk *chunk, int entityCount, EntityRemapUtility.EntityRemapInfo *remapping) { #if !NET_DOTS var managedPatches = archetype->ManagedEntityPatches; var managedPatchCount = archetype->ManagedEntityPatchCount; // Patch managed components with entity references. for (int p = 0; p < managedPatchCount; p++) { var componentType = managedPatches[p].Type; for (int i = 0; i != entityCount; i++) { var obj = managedComponentStore.GetManagedObject(chunk, componentType, i); EntityRemapUtility.PatchEntityInBoxedType(obj, remapping); } } #endif }
public void PatchEntities(Archetype *archetype, Chunk *chunk, int entityCount, EntityRemapUtility.EntityRemapInfo *remapping) { #if !NET_DOTS var firstManagedComponent = archetype->FirstManagedComponent; var numManagedComponents = archetype->NumManagedComponents; for (int i = 0; i < numManagedComponents; ++i) { int type = i + firstManagedComponent; var a = (int *)ChunkDataUtility.GetComponentDataRO(chunk, 0, type); for (int ei = 0; ei < entityCount; ++ei) { if (a[ei] != 0) { var obj = m_ManagedComponentData[a[ei]]; EntityRemapUtility.PatchEntityInBoxedType(obj, remapping); } } } #endif }
public void RemapChunk(Archetype *arch, Chunk *chunk, int baseIndex, int count, ref NativeArray <EntityRemapUtility.EntityRemapInfo> entityRemapping) { Assert.AreEqual(chunk->Archetype->Offsets[0], 0); Assert.AreEqual(chunk->Archetype->SizeOfs[0], sizeof(Entity)); var entityInChunkStart = (Entity *)(chunk->Buffer) + baseIndex; for (var i = 0; i != count; i++) { var entityInChunk = entityInChunkStart + i; var target = EntityRemapUtility.RemapEntity(ref entityRemapping, *entityInChunk); var entity = m_Entities + target.Index; Assert.AreEqual(entity->Version, target.Version); entityInChunk->Index = target.Index; entityInChunk->Version = entity->Version; entity->IndexInChunk = baseIndex + i; entity->Archetype = arch; entity->Chunk = chunk; } }
public void PatchEntitiesForPrefab(ManagedComponentStore managedComponentStore, Archetype *archetype, Chunk *chunk, int indexInChunk, int entityCount, EntityRemapUtility.SparseEntityRemapInfo *remapping, int remappingCount, Allocator allocator) { #if !NET_DOTS var managedPatches = archetype->ManagedEntityPatches; var managedPatchCount = archetype->ManagedEntityPatchCount; // Patch managed components with entity references. for (int p = 0; p < managedPatchCount; p++) { var componentType = managedPatches[p].Type; for (int e = 0; e != entityCount; e++) { var obj = managedComponentStore.GetManagedObject(chunk, componentType, e + indexInChunk); EntityRemapUtility.PatchEntityForPrefabInBoxedType(obj, remapping + e * remappingCount, remappingCount); } } UnsafeUtility.Free(remapping, allocator); #endif }
public void AllocateEntitiesForRemapping(EntityDataManager *srcEntityDataManager, ref NativeArray <EntityRemapUtility.EntityRemapInfo> entityRemapping) { var srcEntityData = srcEntityDataManager->m_Entities; var count = srcEntityDataManager->m_EntitiesCapacity; for (var i = 0; i != count; i++) { if (srcEntityData[i].Chunk != null) { var entity = m_Entities + m_EntitiesFreeIndex; if (entity->IndexInChunk == -1) { IncreaseCapacity(); entity = m_Entities + m_EntitiesFreeIndex; } EntityRemapUtility.AddEntityRemapping(ref entityRemapping, new Entity { Version = srcEntityData[i].Version, Index = i }, new Entity { Version = entity->Version, Index = m_EntitiesFreeIndex }); m_EntitiesFreeIndex = entity->IndexInChunk; } } }
public static void MoveChunks(ArchetypeManager srcArchetypeManager, EntityDataManager *srcEntityDataManager, SharedComponentDataManager srcSharedComponents, ArchetypeManager dstArchetypeManager, EntityGroupManager dstGroupManager, SharedComponentDataManager dstSharedComponentDataManager, EntityDataManager *dstEntityDataManager, SharedComponentDataManager dstSharedComponents) { var entityRemapping = new NativeArray <EntityRemapUtility.EntityRemapInfo>(srcEntityDataManager->Capacity, Allocator.Temp); var entityPatches = new NativeList <EntityRemapUtility.EntityPatchInfo>(128, Allocator.Temp); dstEntityDataManager->AllocateEntitiesForRemapping(srcEntityDataManager, ref entityRemapping); var srcArchetype = srcArchetypeManager.m_LastArchetype; while (srcArchetype != null) { if (srcArchetype->EntityCount != 0) { if (srcArchetype->NumManagedArrays != 0) { throw new ArgumentException("MoveEntitiesFrom is not supported with managed arrays"); } var dstArchetype = dstArchetypeManager.GetOrCreateArchetype(srcArchetype->Types, srcArchetype->TypesCount, dstGroupManager); entityPatches.Clear(); for (var i = 1; i != dstArchetype->TypesCount; i++) { EntityRemapUtility.AppendEntityPatches(ref entityPatches, TypeManager.GetComponentType(dstArchetype->Types[i].TypeIndex).EntityOffsets, dstArchetype->Offsets[i], dstArchetype->SizeOfs[i]); } for (var c = srcArchetype->ChunkList.Begin; c != srcArchetype->ChunkList.End; c = c->Next) { var chunk = (Chunk *)c; dstEntityDataManager->RemapChunk(dstArchetype, chunk, 0, chunk->Count, ref entityRemapping); EntityRemapUtility.PatchEntities(ref entityPatches, chunk->Buffer, chunk->Count, ref entityRemapping); chunk->Archetype = dstArchetype; if (dstArchetype->NumSharedComponents > 0) { dstSharedComponents.MoveSharedComponents(srcSharedComponents, chunk->SharedComponentValueArray, dstArchetype->NumSharedComponents); } } UnsafeLinkedListNode.InsertListBefore(dstArchetype->ChunkList.End, &srcArchetype->ChunkList); if (!srcArchetype->ChunkListWithEmptySlots.IsEmpty) { UnsafeLinkedListNode.InsertListBefore(dstArchetype->ChunkListWithEmptySlots.End, &srcArchetype->ChunkListWithEmptySlots); } dstArchetype->EntityCount += srcArchetype->EntityCount; dstArchetype->ChunkCount += srcArchetype->ChunkCount; srcArchetype->EntityCount = 0; srcArchetype->ChunkCount = 0; } srcArchetype = srcArchetype->PrevArchetype; } srcEntityDataManager->FreeAllEntities(); entityRemapping.Dispose(); entityPatches.Dispose(); }
internal void MoveChunksFromFiltered( NativeArray <ArchetypeChunk> chunks, NativeArray <EntityRemapUtility.EntityRemapInfo> entityRemapping, EntityComponentStore *srcEntityComponentStore, ManagedComponentStore srcManagedComponentStore) { var access = GetCheckedEntityDataAccess(); var ecs = access->EntityComponentStore; var mcs = access->ManagedComponentStore; new MoveChunksJob { srcEntityComponentStore = srcEntityComponentStore, dstEntityComponentStore = ecs, entityRemapping = entityRemapping, chunks = chunks }.Run(); int chunkCount = chunks.Length; var remapChunks = new NativeArray <RemapChunk>(chunkCount, Allocator.TempJob); Archetype *previousSrcArchetypee = null; Archetype *dstArchetype = null; int managedComponentCount = 0; NativeList <IntPtr> managedChunks = new NativeList <IntPtr>(0, Allocator.TempJob); for (int i = 0; i < chunkCount; ++i) { var chunk = chunks[i].m_Chunk; var archetype = chunk->Archetype; // Move Chunk World. ChangeVersion:Yes OrderVersion:Yes if (previousSrcArchetypee != archetype) { dstArchetype = ecs->GetOrCreateArchetype(archetype->Types, archetype->TypesCount); } remapChunks[i] = new RemapChunk { chunk = chunk, dstArchetype = dstArchetype }; if (dstArchetype->NumManagedComponents > 0) { managedComponentCount += chunk->Count * dstArchetype->NumManagedComponents; managedChunks.Add((IntPtr)chunk); } if (archetype->MetaChunkArchetype != null) { Entity srcEntity = chunk->metaChunkEntity; Entity dstEntity; ecs->CreateEntities(dstArchetype->MetaChunkArchetype, &dstEntity, 1); var srcEntityInChunk = srcEntityComponentStore->GetEntityInChunk(srcEntity); var dstEntityInChunk = ecs->GetEntityInChunk(dstEntity); ChunkDataUtility.SwapComponents(srcEntityInChunk.Chunk, srcEntityInChunk.IndexInChunk, dstEntityInChunk.Chunk, dstEntityInChunk.IndexInChunk, 1, srcEntityComponentStore->GlobalSystemVersion, ecs->GlobalSystemVersion); EntityRemapUtility.AddEntityRemapping(ref entityRemapping, srcEntity, dstEntity); srcEntityComponentStore->DestroyEntities(&srcEntity, 1); } } NativeArray <int> srcManagedIndices = default; NativeArray <int> dstManagedIndices = default; int nonNullManagedComponentCount = 0; if (managedComponentCount > 0) { srcManagedIndices = new NativeArray <int>(managedComponentCount, Allocator.TempJob); dstManagedIndices = new NativeArray <int>(managedComponentCount, Allocator.TempJob); new GatherManagedComponentIndicesInChunkJob() { SrcEntityComponentStore = srcEntityComponentStore, DstEntityComponentStore = ecs, SrcManagedIndices = srcManagedIndices, DstManagedIndices = dstManagedIndices, Chunks = managedChunks, NonNullCount = &nonNullManagedComponentCount }.Run(); } mcs.Playback(ref ecs->ManagedChangesTracker); srcManagedComponentStore.Playback(ref srcEntityComponentStore->ManagedChangesTracker); k_ProfileMoveSharedComponents.Begin(); var remapShared = mcs.MoveSharedComponents(srcManagedComponentStore, chunks, Allocator.TempJob); k_ProfileMoveSharedComponents.End(); if (managedComponentCount > 0) { k_ProfileMoveManagedComponents.Begin(); mcs.MoveManagedComponentsFromDifferentWorld(srcManagedIndices, dstManagedIndices, nonNullManagedComponentCount, srcManagedComponentStore); srcEntityComponentStore->m_ManagedComponentFreeIndex.Add(srcManagedIndices.GetUnsafeReadOnlyPtr(), sizeof(int) * srcManagedIndices.Length); k_ProfileMoveManagedComponents.End(); } new ChunkPatchEntities { RemapChunks = remapChunks, EntityRemapping = entityRemapping, EntityComponentStore = ecs }.Run(); var remapChunksJob = new RemapChunksFilteredJob { dstEntityComponentStore = ecs, remapChunks = remapChunks, entityRemapping = entityRemapping, chunkHeaderType = TypeManager.GetTypeIndex <ChunkHeader>() }.Schedule(remapChunks.Length, 1); var moveChunksBetweenArchetypeJob = new MoveFilteredChunksBetweenArchetypexJob { RemapChunks = remapChunks, RemapShared = remapShared, GlobalSystemVersion = ecs->GlobalSystemVersion }.Schedule(remapChunksJob); moveChunksBetweenArchetypeJob.Complete(); mcs.Playback(ref ecs->ManagedChangesTracker); if (managedComponentCount > 0) { srcManagedIndices.Dispose(); dstManagedIndices.Dispose(); } managedChunks.Dispose(); remapShared.Dispose(); remapChunks.Dispose(); }
void InstantiateEntitiesGroup(Entity *srcEntities, int srcEntityCount, Entity *outputRootEntities, int instanceCount) { int totalCount = srcEntityCount * instanceCount; var tempAllocSize = sizeof(EntityRemapUtility.SparseEntityRemapInfo) * totalCount + sizeof(InstantiateRemapChunk) * totalCount + sizeof(Entity) * instanceCount; byte * allocation; const int kMaxStackAllocSize = 16 * 1024; if (tempAllocSize > kMaxStackAllocSize) { allocation = (byte *)UnsafeUtility.Malloc(tempAllocSize, 16, Allocator.Temp); } else { var temp = stackalloc byte[tempAllocSize]; allocation = temp; } var entityRemap = (EntityRemapUtility.SparseEntityRemapInfo *)allocation; var remapChunks = (InstantiateRemapChunk *)(entityRemap + totalCount); var outputEntities = (Entity *)(remapChunks + totalCount); var remapChunksCount = 0; for (int i = 0; i != srcEntityCount; i++) { var srcEntity = srcEntities[i]; remapChunksCount = InstantiateEntitiesOne(srcEntity, outputEntities, instanceCount, remapChunks, remapChunksCount); for (int r = 0; r != instanceCount; r++) { var ptr = entityRemap + (r * srcEntityCount + i); ptr->Src = srcEntity; ptr->Target = outputEntities[r]; } if (i == 0) { for (int r = 0; r != instanceCount; r++) { outputRootEntities[r] = outputEntities[r]; } } } for (int i = 0; i != remapChunksCount; i++) { var chunk = remapChunks[i].Chunk; var dstArchetype = chunk->Archetype; var allocatedCount = remapChunks[i].AllocatedCount; var indexInChunk = remapChunks[i].IndexInChunk; var instanceBeginIndex = remapChunks[i].InstanceBeginIndex; var localRemap = entityRemap + instanceBeginIndex * srcEntityCount; EntityRemapUtility.PatchEntitiesForPrefab(dstArchetype->ScalarEntityPatches + 1, dstArchetype->ScalarEntityPatchCount - 1, dstArchetype->BufferEntityPatches, dstArchetype->BufferEntityPatchCount, chunk->Buffer, indexInChunk, allocatedCount, localRemap, srcEntityCount); ManagedChangesTracker.PatchEntitiesForPrefab(dstArchetype, chunk, indexInChunk, allocatedCount, localRemap, srcEntityCount, Allocator.Temp); } if (tempAllocSize > kMaxStackAllocSize) { UnsafeUtility.Free(allocation, Allocator.Temp); } }
private static ComponentType BuildComponentType(Type type) { var componentSize = 0; TypeCategory category; FastEquality.Layout[] fastEqualityLayout = null; EntityOffsetInfo[] entityOffsets = null; var memoryOrdering = CalculateMemoryOrdering(type); if (typeof(IComponentData).IsAssignableFrom(type)) { #if ENABLE_UNITY_COLLECTIONS_CHECKS if (type.IsClass) { throw new ArgumentException($"{type} is an IComponentData, and thus must be a struct."); } if (!UnsafeUtility.IsBlittable(type)) { throw new ArgumentException( $"{type} is an IComponentData, and thus must be blittable (No managed object is allowed on the struct)."); } #endif category = TypeCategory.ComponentData; componentSize = UnsafeUtility.SizeOf(type); fastEqualityLayout = FastEquality.CreateLayout(type); entityOffsets = EntityRemapUtility.CalculateEntityOffsets(type); } else if (typeof(ISharedComponentData).IsAssignableFrom(type)) { #if ENABLE_UNITY_COLLECTIONS_CHECKS if (type.IsClass) { throw new ArgumentException($"{type} is an ISharedComponentData, and thus must be a struct."); } #endif category = TypeCategory.ISharedComponentData; fastEqualityLayout = FastEquality.CreateLayout(type); } else if (type.IsValueType) { #if ENABLE_UNITY_COLLECTIONS_CHECKS if (!UnsafeUtility.IsBlittable(type)) { throw new ArgumentException($"{type} is used for FixedArrays, and thus must be blittable."); } #endif category = TypeCategory.OtherValueType; componentSize = UnsafeUtility.SizeOf(type); } else if (type.IsClass) { category = TypeCategory.Class; #if ENABLE_UNITY_COLLECTIONS_CHECKS if (type.FullName == "Unity.Entities.GameObjectEntity") { throw new ArgumentException( "GameObjectEntity can not be used from EntityManager. The component is ignored when creating entities for a GameObject."); } #endif } #if ENABLE_UNITY_COLLECTIONS_CHECKS else { throw new ArgumentException($"'{type}' is not a valid component"); }
public static TypeInfo BuildComponentType(Type type) { TypeCategory componentData; int size = 0; FastEquality.TypeInfo @null = FastEquality.TypeInfo.Null; EntityOffsetInfo[] entityOffsets = null; int bufferCapacity = -1; ulong memoryOrdering = CalculateMemoryOrdering(type); int num4 = 0; if (type.IsInterface) { throw new ArgumentException($"{type} is an interface. It must be a concrete type."); } if (typeof(IComponentData).IsAssignableFrom(type)) { if (!type.IsValueType) { throw new ArgumentException($"{type} is an IComponentData, and thus must be a struct."); } if (!UnsafeUtility.IsBlittable(type)) { throw new ArgumentException($"{type} is an IComponentData, and thus must be blittable (No managed object is allowed on the struct)."); } componentData = TypeCategory.ComponentData; if (IsZeroSizeStruct(type)) { size = 0; } else { size = UnsafeUtility.SizeOf(type); } @null = FastEquality.CreateTypeInfo(type); entityOffsets = EntityRemapUtility.CalculateEntityOffsets(type); } else if (typeof(IBufferElementData).IsAssignableFrom(type)) { if (!type.IsValueType) { throw new ArgumentException($"{type} is an IBufferElementData, and thus must be a struct."); } if (!UnsafeUtility.IsBlittable(type)) { throw new ArgumentException($"{type} is an IBufferElementData, and thus must be blittable (No managed object is allowed on the struct)."); } componentData = TypeCategory.BufferData; num4 = UnsafeUtility.SizeOf(type); InternalBufferCapacityAttribute customAttribute = (InternalBufferCapacityAttribute)type.GetCustomAttribute(typeof(InternalBufferCapacityAttribute)); if (customAttribute != null) { bufferCapacity = customAttribute.Capacity; } else { bufferCapacity = 0x80 / num4; } size = sizeof(BufferHeader) + (bufferCapacity * num4); @null = FastEquality.CreateTypeInfo(type); entityOffsets = EntityRemapUtility.CalculateEntityOffsets(type); } else if (typeof(ISharedComponentData).IsAssignableFrom(type)) { if (!type.IsValueType) { throw new ArgumentException($"{type} is an ISharedComponentData, and thus must be a struct."); } componentData = TypeCategory.ISharedComponentData; @null = FastEquality.CreateTypeInfo(type); } else { if (!type.IsClass) { throw new ArgumentException($"{type} is not a valid component."); } componentData = TypeCategory.Class; if (type.FullName == "Unity.Entities.GameObjectEntity") { throw new ArgumentException("GameObjectEntity cannot be used from EntityManager. The component is ignored when creating entities for a GameObject."); } if (UnityEngineComponentType == null) { throw new ArgumentException($"{type} cannot be used from EntityManager. If it inherits UnityEngine.Component, you must first register {typeof(TypeManager)}.{"UnityEngineComponentType"} or include the Unity.Entities.Hybrid assembly in your build."); } if (!UnityEngineComponentType.IsAssignableFrom(type)) { throw new ArgumentException($"{type} must inherit {UnityEngineComponentType}."); } } int num5 = 0; foreach (Type type2 in s_SingularInterfaces) { if (type2.IsAssignableFrom(type)) { num5++; } } if (num5 > 1) { throw new ArgumentException($"Component {type} can only implement one of IComponentData, ISharedComponentData and IBufferElementData"); } return(new TypeInfo(type, size, componentData, @null, entityOffsets, memoryOrdering, bufferCapacity, (num4 > 0) ? num4 : size)); }
/// <summary> /// Moves all entities managed by the specified EntityManager to the <see cref="World"/> of this EntityManager and fills /// an array with their <see cref="Entity"/> objects. /// </summary> /// <remarks> /// After the move, the entities are managed by this EntityManager. Use the `output` array to make post-move /// changes to the transferred entities. /// /// Each world has one EntityManager, which manages all the entities in that world. This function /// allows you to transfer entities from one World to another. /// /// **Important:** This function creates a sync point, which means that the EntityManager waits for all /// currently running Jobs to complete before moving the entities and no additional Jobs can start before /// the function is finished. A sync point can cause a drop in performance because the ECS framework may not /// be able to make use of the processing power of all available cores. /// </remarks> /// <param name="output">An array to receive the Entity objects of the transferred entities.</param> /// <param name="srcEntities">The EntityManager whose entities are appropriated.</param> /// <param name="entityRemapping">A set of entity transformations to make during the transfer.</param> /// <exception cref="ArgumentException"></exception> public void MoveEntitiesFrom(out NativeArray <Entity> output, EntityManager srcEntities, NativeArray <EntityRemapUtility.EntityRemapInfo> entityRemapping) { MoveEntitiesFromInternalAll(srcEntities, entityRemapping); EntityRemapUtility.GetTargets(out output, entityRemapping); }
internal void MoveChunksFrom( NativeArray <ArchetypeChunk> chunks, NativeArray <EntityRemapUtility.EntityRemapInfo> entityRemapping, EntityComponentStore *srcEntityComponentStore, ManagedComponentStore srcManagedComponentStore) { new MoveChunksJob { srcEntityComponentStore = srcEntityComponentStore, dstEntityComponentStore = EntityComponentStore, entityRemapping = entityRemapping, chunks = chunks }.Run(); var managedArrayChunks = new NativeList <IntPtr>(Allocator.Temp); int chunkCount = chunks.Length; var remapChunks = new NativeArray <RemapChunk>(chunkCount, Allocator.TempJob); for (int i = 0; i < chunkCount; ++i) { var chunk = chunks[i].m_Chunk; var archetype = chunk->Archetype; //TODO: this should not be done more than once for each archetype var dstArchetype = EntityComponentStore->GetOrCreateArchetype(archetype->Types, archetype->TypesCount); remapChunks[i] = new RemapChunk { chunk = chunk, dstArchetype = dstArchetype }; if (archetype->NumManagedArrays > 0) { managedArrayChunks.Add((IntPtr)chunk); } if (archetype->MetaChunkArchetype != null) { Entity srcEntity = chunk->metaChunkEntity; Entity dstEntity; EntityComponentStore->CreateEntities(dstArchetype->MetaChunkArchetype, &dstEntity, 1); var srcEntityInChunk = srcEntityComponentStore->GetEntityInChunk(srcEntity); var dstEntityInChunk = EntityComponentStore->GetEntityInChunk(dstEntity); ChunkDataUtility.SwapComponents(srcEntityInChunk.Chunk, srcEntityInChunk.IndexInChunk, dstEntityInChunk.Chunk, dstEntityInChunk.IndexInChunk, 1, srcEntityComponentStore->GlobalSystemVersion, EntityComponentStore->GlobalSystemVersion); EntityRemapUtility.AddEntityRemapping(ref entityRemapping, srcEntity, dstEntity); srcEntityComponentStore->DestroyEntities(&srcEntity, 1); } } var managedArrayDstIndices = new NativeArray <int>(managedArrayChunks.Length, Allocator.TempJob); var managedArraySrcIndices = new NativeArray <int>(managedArrayChunks.Length, Allocator.TempJob); EntityComponentStore->ReserveManagedObjectArrays(managedArrayDstIndices); var remapManaged = new RemapManagedArraysJob { chunks = managedArrayChunks, dstIndices = managedArrayDstIndices, srcIndices = managedArraySrcIndices, }.Schedule(managedArrayChunks.Length, 64); ManagedComponentStore.Playback(ref EntityComponentStore->ManagedChangesTracker); srcManagedComponentStore.Playback(ref srcEntityComponentStore->ManagedChangesTracker); k_ProfileMoveObjectComponents.Begin(); remapManaged.Complete(); m_ManagedComponentStore.MoveManagedObjectArrays(managedArraySrcIndices, managedArrayDstIndices, srcManagedComponentStore); k_ProfileMoveObjectComponents.End(); managedArrayDstIndices.Dispose(); managedArraySrcIndices.Dispose(); managedArrayChunks.Dispose(); k_ProfileMoveSharedComponents.Begin(); var remapShared = ManagedComponentStore.MoveSharedComponents(srcManagedComponentStore, chunks, Allocator.TempJob); k_ProfileMoveSharedComponents.End(); new ChunkPatchEntities { RemapChunks = remapChunks, EntityRemapping = entityRemapping, EntityComponentStore = EntityComponentStore }.Run(); var remapChunksJob = new RemapChunksJob { dstEntityComponentStore = EntityComponentStore, remapChunks = remapChunks, entityRemapping = entityRemapping }.Schedule(remapChunks.Length, 1); var moveChunksBetweenArchetypeJob = new MoveChunksBetweenArchetypeJob { remapChunks = remapChunks, remapShared = remapShared, globalSystemVersion = EntityComponentStore->GlobalSystemVersion }.Schedule(remapChunksJob); moveChunksBetweenArchetypeJob.Complete(); ManagedComponentStore.Playback(ref EntityComponentStore->ManagedChangesTracker); remapShared.Dispose(); remapChunks.Dispose(); }
internal static TypeInfo BuildComponentType(Type type, int *writeGroups, int writeGroupCount) { var componentSize = 0; TypeCategory category; var typeInfo = FastEquality.TypeInfo.Null; EntityOffsetInfo[] entityOffsets = null; EntityOffsetInfo[] blobAssetRefOffsets = null; int bufferCapacity = -1; var memoryOrdering = CalculateMemoryOrdering(type); var stableTypeHash = CalculateStableTypeHash(type); var maxChunkCapacity = int.MaxValue; var maxCapacityAttribute = type.GetCustomAttribute <MaximumChunkCapacityAttribute>(); if (maxCapacityAttribute != null) { maxChunkCapacity = maxCapacityAttribute.Capacity; } int elementSize = 0; int alignmentInBytes = 0; #if ENABLE_UNITY_COLLECTIONS_CHECKS if (type.IsInterface) { throw new ArgumentException($"{type} is an interface. It must be a concrete type."); } #endif if (typeof(IComponentData).IsAssignableFrom(type)) { CheckIsAllowedAsComponentData(type, nameof(IComponentData)); category = TypeCategory.ComponentData; if (TypeManager.IsZeroSizeStruct(type)) { componentSize = 0; } else { componentSize = UnsafeUtility.SizeOf(type); } typeInfo = FastEquality.CreateTypeInfo(type); entityOffsets = EntityRemapUtility.CalculateEntityOffsets(type); blobAssetRefOffsets = CalculatBlobAssetRefOffsets(type); int sizeInBytes = UnsafeUtility.SizeOf(type); // TODO: Implement UnsafeUtility.AlignOf(type) alignmentInBytes = 16; if (sizeInBytes < 16 && (sizeInBytes & (sizeInBytes - 1)) == 0) { alignmentInBytes = sizeInBytes; } } else if (typeof(IBufferElementData).IsAssignableFrom(type)) { CheckIsAllowedAsComponentData(type, nameof(IBufferElementData)); category = TypeCategory.BufferData; elementSize = UnsafeUtility.SizeOf(type); var capacityAttribute = (InternalBufferCapacityAttribute)type.GetCustomAttribute(typeof(InternalBufferCapacityAttribute)); if (capacityAttribute != null) { bufferCapacity = capacityAttribute.Capacity; } else { bufferCapacity = 128 / elementSize; // Rather than 2*cachelinesize, to make it cross platform deterministic } componentSize = sizeof(BufferHeader) + bufferCapacity * elementSize; typeInfo = FastEquality.CreateTypeInfo(type); entityOffsets = EntityRemapUtility.CalculateEntityOffsets(type); blobAssetRefOffsets = CalculatBlobAssetRefOffsets(type); int sizeInBytes = UnsafeUtility.SizeOf(type); // TODO: Implement UnsafeUtility.AlignOf(type) alignmentInBytes = 16; if (sizeInBytes < 16 && (sizeInBytes & (sizeInBytes - 1)) == 0) { alignmentInBytes = sizeInBytes; } } else if (typeof(ISharedComponentData).IsAssignableFrom(type)) { #if ENABLE_UNITY_COLLECTIONS_CHECKS if (!type.IsValueType) { throw new ArgumentException($"{type} is an ISharedComponentData, and thus must be a struct."); } #endif entityOffsets = EntityRemapUtility.CalculateEntityOffsets(type); category = TypeCategory.ISharedComponentData; typeInfo = FastEquality.CreateTypeInfo(type); } else if (type.IsClass) { category = TypeCategory.Class; #if ENABLE_UNITY_COLLECTIONS_CHECKS if (type.FullName == "Unity.Entities.GameObjectEntity") { throw new ArgumentException( "GameObjectEntity cannot be used from EntityManager. The component is ignored when creating entities for a GameObject."); } if (UnityEngineComponentType == null) { throw new ArgumentException( $"{type} cannot be used from EntityManager. If it inherits UnityEngine.Component, you must first register TypeManager.UnityEngineComponentType or include the Unity.Entities.Hybrid assembly in your build."); } if (!UnityEngineComponentType.IsAssignableFrom(type)) { throw new ArgumentException($"{type} must inherit {UnityEngineComponentType}."); } #endif } else { throw new ArgumentException($"{type} is not a valid component."); } #if ENABLE_UNITY_COLLECTIONS_CHECKS CheckComponentType(type); #endif int typeIndex = s_Count; return(new TypeInfo(type, typeIndex, componentSize, category, typeInfo, entityOffsets, blobAssetRefOffsets, memoryOrdering, bufferCapacity, elementSize > 0 ? elementSize : componentSize, alignmentInBytes, stableTypeHash, writeGroups, writeGroupCount, maxChunkCapacity)); }
public Archetype *GetOrCreateArchetype(ComponentTypeInArchetype *types, int count, EntityGroupManager groupManager) { var type = GetExistingArchetype(types, count); if (type != null) { return(type); } AssertArchetypeComponents(types, count); // This is a new archetype, allocate it and add it to the hash map type = (Archetype *)m_ArchetypeChunkAllocator.Allocate(sizeof(Archetype), 8); type->TypesCount = count; type->Types = (ComponentTypeInArchetype *)m_ArchetypeChunkAllocator.Construct( sizeof(ComponentTypeInArchetype) * count, 4, types); type->EntityCount = 0; type->ChunkCount = 0; type->NumSharedComponents = 0; type->SharedComponentOffset = null; var disabledTypeIndex = TypeManager.GetTypeIndex <Disabled>(); type->Disabled = false; for (var i = 0; i < count; ++i) { if (TypeManager.GetComponentType(types[i].TypeIndex).Category == TypeManager.TypeCategory.ISharedComponentData) { ++type->NumSharedComponents; } if (types[i].TypeIndex == disabledTypeIndex) { type->Disabled = true; } } // Compute how many IComponentData types store Entities and need to be patched. // Types can have more than one entity, which means that this count is not necessarily // the same as the type count. int scalarEntityPatchCount = 0; int bufferEntityPatchCount = 0; for (var i = 0; i < count; ++i) { var ct = TypeManager.GetComponentType(types[i].TypeIndex); var entityOffsets = ct.EntityOffsets; if (entityOffsets == null) { continue; } if (ct.BufferCapacity >= 0) { bufferEntityPatchCount += entityOffsets.Length; } else { scalarEntityPatchCount += entityOffsets.Length; } } var chunkDataSize = Chunk.GetChunkBufferSize(type->TypesCount, type->NumSharedComponents); // FIXME: proper alignment type->Offsets = (int *)m_ArchetypeChunkAllocator.Allocate(sizeof(int) * count, 4); type->SizeOfs = (int *)m_ArchetypeChunkAllocator.Allocate(sizeof(int) * count, 4); type->TypeMemoryOrder = (int *)m_ArchetypeChunkAllocator.Allocate(sizeof(int) * count, 4); type->ScalarEntityPatches = (EntityRemapUtility.EntityPatchInfo *)m_ArchetypeChunkAllocator.Allocate(sizeof(EntityRemapUtility.EntityPatchInfo) * scalarEntityPatchCount, 4); type->ScalarEntityPatchCount = scalarEntityPatchCount; type->BufferEntityPatches = (EntityRemapUtility.BufferEntityPatchInfo *)m_ArchetypeChunkAllocator.Allocate(sizeof(EntityRemapUtility.BufferEntityPatchInfo) * bufferEntityPatchCount, 4); type->BufferEntityPatchCount = bufferEntityPatchCount; var bytesPerInstance = 0; for (var i = 0; i < count; ++i) { var cType = TypeManager.GetComponentType(types[i].TypeIndex); var sizeOf = cType.SizeInChunk; // Note that this includes internal capacity and header overhead for buffers. type->SizeOfs[i] = sizeOf; bytesPerInstance += sizeOf; } type->ChunkCapacity = chunkDataSize / bytesPerInstance; #if ENABLE_UNITY_COLLECTIONS_CHECKS if (bytesPerInstance > chunkDataSize) { throw new ArgumentException( $"Entity archetype component data is too large. The maximum component data is {chunkDataSize} but the component data is {bytesPerInstance}"); } Assert.IsTrue(Chunk.kMaximumEntitiesPerChunk >= type->ChunkCapacity); #endif // For serialization a stable ordering of the components in the // chunk is desired. The type index is not stable, since it depends // on the order in which types are added to the TypeManager. // A permutation of the types ordered by a TypeManager-generated // memory ordering is used instead. var memoryOrderings = new NativeArray <UInt64>(count, Allocator.Temp); for (int i = 0; i < count; ++i) { memoryOrderings[i] = TypeManager.GetComponentType(types[i].TypeIndex).MemoryOrdering; } for (int i = 0; i < count; ++i) { int index = i; while (index > 1 && memoryOrderings[i] < memoryOrderings[type->TypeMemoryOrder[index - 1]]) { type->TypeMemoryOrder[index] = type->TypeMemoryOrder[index - 1]; --index; } type->TypeMemoryOrder[index] = i; } memoryOrderings.Dispose(); var usedBytes = 0; for (var i = 0; i < count; ++i) { var index = type->TypeMemoryOrder[i]; var sizeOf = type->SizeOfs[index]; type->Offsets[index] = usedBytes; usedBytes += sizeOf * type->ChunkCapacity; } type->NumManagedArrays = 0; type->ManagedArrayOffset = null; for (var i = 0; i < count; ++i) { if (TypeManager.GetComponentType(types[i].TypeIndex).Category == TypeManager.TypeCategory.Class) { ++type->NumManagedArrays; } } if (type->NumManagedArrays > 0) { type->ManagedArrayOffset = (int *)m_ArchetypeChunkAllocator.Allocate(sizeof(int) * count, 4); var mi = 0; for (var i = 0; i < count; ++i) { var cType = TypeManager.GetComponentType(types[i].TypeIndex); if (cType.Category == TypeManager.TypeCategory.Class) { type->ManagedArrayOffset[i] = mi++; } else { type->ManagedArrayOffset[i] = -1; } } } if (type->NumSharedComponents > 0) { type->SharedComponentOffset = (int *)m_ArchetypeChunkAllocator.Allocate(sizeof(int) * count, 4); var mi = 0; for (var i = 0; i < count; ++i) { var cType = TypeManager.GetComponentType(types[i].TypeIndex); if (cType.Category == TypeManager.TypeCategory.ISharedComponentData) { type->SharedComponentOffset[i] = mi++; } else { type->SharedComponentOffset[i] = -1; } } } // Fill in arrays of scalar and buffer entity patches var scalarPatchInfo = type->ScalarEntityPatches; var bufferPatchInfo = type->BufferEntityPatches; for (var i = 0; i != count; i++) { var ct = TypeManager.GetComponentType(types[i].TypeIndex); var offsets = ct.EntityOffsets; if (ct.BufferCapacity >= 0) { bufferPatchInfo = EntityRemapUtility.AppendBufferEntityPatches(bufferPatchInfo, offsets, type->Offsets[i], type->SizeOfs[i], ct.ElementSize); } else { scalarPatchInfo = EntityRemapUtility.AppendEntityPatches(scalarPatchInfo, offsets, type->Offsets[i], type->SizeOfs[i]); } } type->ScalarEntityPatchCount = scalarEntityPatchCount; type->BufferEntityPatchCount = bufferEntityPatchCount; // Update the list of all created archetypes type->PrevArchetype = m_LastArchetype; m_LastArchetype = type; UnsafeLinkedListNode.InitializeList(&type->ChunkList); UnsafeLinkedListNode.InitializeList(&type->ChunkListWithEmptySlots); type->FreeChunksBySharedComponents.Init(8); m_TypeLookup.Add(GetHash(types, count), (IntPtr)type); type->SystemStateCleanupComplete = ArchetypeSystemStateCleanupComplete(type); type->SystemStateCleanupNeeded = ArchetypeSystemStateCleanupNeeded(type); groupManager.OnArchetypeAdded(type); return(type); }
public static TypeInfo BuildComponentType(Type type) { var componentSize = 0; TypeCategory category; var typeInfo = FastEquality.TypeInfo.Null; EntityOffsetInfo[] entityOffsets = null; int bufferCapacity = -1; var memoryOrdering = CalculateMemoryOrdering(type); int elementSize = 0; if (typeof(IComponentData).IsAssignableFrom(type)) { #if ENABLE_UNITY_COLLECTIONS_CHECKS if (!type.IsValueType) { throw new ArgumentException($"{type} is an IComponentData, and thus must be a struct."); } if (!UnsafeUtility.IsBlittable(type)) { throw new ArgumentException( $"{type} is an IComponentData, and thus must be blittable (No managed object is allowed on the struct)."); } #endif category = TypeCategory.ComponentData; if (TypeManager.IsZeroSizeStruct(type)) { componentSize = 0; } else { componentSize = UnsafeUtility.SizeOf(type); } typeInfo = FastEquality.CreateTypeInfo(type); entityOffsets = EntityRemapUtility.CalculateEntityOffsets(type); } else if (typeof(IBufferElementData).IsAssignableFrom(type)) { #if ENABLE_UNITY_COLLECTIONS_CHECKS if (!type.IsValueType) { throw new ArgumentException($"{type} is an IBufferElementData, and thus must be a struct."); } if (!UnsafeUtility.IsBlittable(type)) { throw new ArgumentException( $"{type} is an IBufferElementData, and thus must be blittable (No managed object is allowed on the struct)."); } #endif category = TypeCategory.BufferData; elementSize = UnsafeUtility.SizeOf(type); var capacityAttribute = (InternalBufferCapacityAttribute)type.GetCustomAttribute(typeof(InternalBufferCapacityAttribute)); if (capacityAttribute != null) { bufferCapacity = capacityAttribute.Capacity; } else { bufferCapacity = 128 / elementSize; // Rather than 2*cachelinesize, to make it cross platform deterministic } componentSize = sizeof(BufferHeader) + bufferCapacity * elementSize; typeInfo = FastEquality.CreateTypeInfo(type); entityOffsets = EntityRemapUtility.CalculateEntityOffsets(type); } else if (typeof(ISharedComponentData).IsAssignableFrom(type)) { #if ENABLE_UNITY_COLLECTIONS_CHECKS if (!type.IsValueType) { throw new ArgumentException($"{type} is an ISharedComponentData, and thus must be a struct."); } #endif category = TypeCategory.ISharedComponentData; typeInfo = FastEquality.CreateTypeInfo(type); } else if (type.IsClass) { category = TypeCategory.Class; #if ENABLE_UNITY_COLLECTIONS_CHECKS if (type.FullName == "Unity.Entities.GameObjectEntity") { throw new ArgumentException( "GameObjectEntity can not be used from EntityManager. The component is ignored when creating entities for a GameObject."); } #endif } else { throw new ArgumentException($"'{type}' is not a valid component"); } #if ENABLE_UNITY_COLLECTIONS_CHECKS { int typeCount = 0; foreach (Type t in s_SingularInterfaces) { if (t.IsAssignableFrom(type)) { ++typeCount; } } if (typeCount > 1) { throw new ArgumentException($"Component {type} can only implement one of IComponentData, ISharedComponentData and IBufferElementData"); } } #endif return(new TypeInfo(type, componentSize, category, typeInfo, entityOffsets, memoryOrdering, bufferCapacity, elementSize > 0 ? elementSize : componentSize)); }
public static void MoveChunks( NativeArray <ArchetypeChunk> chunks, NativeArray <EntityRemapUtility.EntityRemapInfo> entityRemapping, EntityComponentStore *srcEntityComponentStore, ManagedComponentStore srcManagedComponentStore, EntityComponentStore *dstEntityComponentStore, ManagedComponentStore dstManagedComponentStore) { new MoveChunksJob { srcEntityComponentStore = srcEntityComponentStore, dstEntityComponentStore = dstEntityComponentStore, entityRemapping = entityRemapping, chunks = chunks }.Run(); int chunkCount = chunks.Length; var remapChunks = new NativeArray <RemapChunk>(chunkCount, Allocator.TempJob); for (int i = 0; i < chunkCount; ++i) { var chunk = chunks[i].m_Chunk; var archetype = chunk->Archetype; //TODO: this should not be done more than once for each archetype var dstArchetype = EntityManagerCreateArchetypeUtility.GetOrCreateArchetype(archetype->Types, archetype->TypesCount, dstEntityComponentStore); remapChunks[i] = new RemapChunk { chunk = chunk, dstArchetype = dstArchetype }; chunk->SequenceNumber = dstEntityComponentStore->AssignSequenceNumber(chunk); if (archetype->MetaChunkArchetype != null) { Entity srcEntity = chunk->metaChunkEntity; Entity dstEntity; EntityManagerCreateDestroyEntitiesUtility.CreateEntities(dstArchetype->MetaChunkArchetype, &dstEntity, 1, dstEntityComponentStore, dstManagedComponentStore); srcEntityComponentStore->GetChunk(srcEntity, out var srcChunk, out var srcIndex); dstEntityComponentStore->GetChunk(dstEntity, out var dstChunk, out var dstIndex); ChunkDataUtility.SwapComponents(srcChunk, srcIndex, dstChunk, dstIndex, 1, srcEntityComponentStore->GlobalSystemVersion, dstEntityComponentStore->GlobalSystemVersion); EntityRemapUtility.AddEntityRemapping(ref entityRemapping, srcEntity, dstEntity); EntityManagerCreateDestroyEntitiesUtility.DestroyEntities(&srcEntity, 1, srcEntityComponentStore, srcManagedComponentStore); } } k_ProfileMoveSharedComponents.Begin(); var remapShared = dstManagedComponentStore.MoveSharedComponents(srcManagedComponentStore, chunks, entityRemapping, Allocator.TempJob); k_ProfileMoveSharedComponents.End(); var remapChunksJob = new RemapChunksJob { dstEntityComponentStore = dstEntityComponentStore, remapChunks = remapChunks, entityRemapping = entityRemapping }.Schedule(remapChunks.Length, 1); var moveChunksBetweenArchetypeJob = new MoveChunksBetweenArchetypeJob { remapChunks = remapChunks, remapShared = remapShared, globalSystemVersion = dstEntityComponentStore->GlobalSystemVersion }.Schedule(remapChunksJob); moveChunksBetweenArchetypeJob.Complete(); remapShared.Dispose(); remapChunks.Dispose(); }
unsafe public VisitStatus Visit <TProperty, TContainer>(IPropertyVisitor visitor, TProperty property, ref TContainer container, ref Entity value, ref ChangeTracker changeTracker) where TProperty : IProperty <TContainer, Entity> { value = EntityRemapUtility.RemapEntityForPrefab(RemapInfo, RemapInfoCount, value); return(VisitStatus.Handled); }
public static void Initialize() { if (s_Types != null) { return; } ObjectOffset = UnsafeUtility.SizeOf <ObjectOffsetType>(); s_CreateTypeLock = new SpinLock(); s_Types = new TypeInfo[MaximumTypesCount]; s_Count = 0; s_Types[s_Count++] = new TypeInfo(null, 0, TypeCategory.ComponentData, FastEquality.TypeInfo.Null, null, 0, -1, 0); // This must always be first so that Entity is always index 0 in the archetype s_Types[s_Count++] = new TypeInfo(typeof(Entity), sizeof(Entity), TypeCategory.EntityData, FastEquality.CreateTypeInfo(typeof(Entity)), EntityRemapUtility.CalculateEntityOffsets(typeof(Entity)), 0, -1, sizeof(Entity)); }
public static void Initialize() { if (s_Types == null) { ObjectOffset = UnsafeUtility.SizeOf <ObjectOffsetType>(); s_CreateTypeLock = new System.Threading.SpinLock(); s_Types = new TypeInfo[0x2800]; s_Count = 0; s_Count++; s_Types[s_Count] = new TypeInfo(null, 0, TypeCategory.ComponentData, FastEquality.TypeInfo.Null, null, 0L, -1, 0); s_Count++; s_Types[s_Count] = new TypeInfo(typeof(Entity), sizeof(Entity), TypeCategory.EntityData, FastEquality.CreateTypeInfo(typeof(Entity)), EntityRemapUtility.CalculateEntityOffsets(typeof(Entity)), 0L, -1, sizeof(Entity)); } }