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); //@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(); }
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); }
private static void ApplySetSharedComponents( EntityManager entityManager, PackedSharedComponentDataChange[] sharedComponentDataChanges, NativeArray <EntityGuid> packedEntityGuid, NativeMultiHashMap <int, Entity> packedEntities, NativeArray <ComponentType> packedTypes) { for (var i = 0; i < sharedComponentDataChanges.Length; i++) { var packedSharedComponentDataChange = sharedComponentDataChanges[i]; var packedComponent = packedSharedComponentDataChange.Component; if (!packedEntities.TryGetFirstValue(packedComponent.PackedEntityIndex, out var entity, out var iterator)) { continue; } var component = packedTypes[packedComponent.PackedTypeIndex]; do { if (!entityManager.Exists(entity)) { Debug.LogWarning($"SetComponent<{component}>({packedEntityGuid[packedComponent.PackedEntityIndex]}) but entity does not exist."); } else if (!entityManager.HasComponent(entity, component)) { Debug.LogWarning($"SetComponent<{component}>({packedEntityGuid[packedComponent.PackedEntityIndex]}) but component does not exist."); } else { entityManager.SetSharedComponentDataBoxedDefaultMustBeNull(entity, component.TypeIndex, packedSharedComponentDataChange.BoxedSharedValue); } }while (packedEntities.TryGetNextValue(out entity, ref iterator)); } }
public bool Exists(Entity entity) { return(m_Manager.Exists(entity)); }
static void ApplyBlobAssetChanges( EntityManager entityManager, NativeArray <EntityGuid> packedEntityGuids, NativeMultiHashMap <int, Entity> packedEntities, NativeArray <ComponentType> packedTypes, NativeArray <BlobAssetChange> createdBlobAssets, NativeArray <byte> createdBlobAssetData, NativeArray <ulong> destroyedBlobAssets, NativeArray <BlobAssetReferenceChange> blobAssetReferenceChanges) { if (createdBlobAssets.Length == 0 && blobAssetReferenceChanges.Length == 0) { return; } var patcherBlobAssetSystem = entityManager.World.GetOrCreateSystem <EntityPatcherBlobAssetSystem>(); var blobAssetDataPtr = (byte *)createdBlobAssetData.GetUnsafePtr(); for (var i = 0; i < createdBlobAssets.Length; i++) { if (!patcherBlobAssetSystem.TryGetBlobAsset(createdBlobAssets[i].Hash, out _)) { patcherBlobAssetSystem.AllocateBlobAsset(blobAssetDataPtr, createdBlobAssets[i].Length, createdBlobAssets[i].Hash); } blobAssetDataPtr += createdBlobAssets[i].Length; } for (var i = 0; i < destroyedBlobAssets.Length; i++) { patcherBlobAssetSystem.ReleaseBlobAsset(destroyedBlobAssets[i]); } for (var i = 0; i < blobAssetReferenceChanges.Length; i++) { var packedComponent = blobAssetReferenceChanges[i].Component; var component = packedTypes[packedComponent.PackedTypeIndex]; var targetOffset = blobAssetReferenceChanges[i].Offset; BlobAssetReferenceData targetBlobAssetReferenceData; if (patcherBlobAssetSystem.TryGetBlobAsset(blobAssetReferenceChanges[i].Value, out var blobAssetPtr)) { targetBlobAssetReferenceData = new BlobAssetReferenceData { m_Ptr = (byte *)blobAssetPtr.Data }; } if (packedEntities.TryGetFirstValue(packedComponent.PackedEntityIndex, out var entity, out var iterator)) { do { if (!entityManager.Exists(entity)) { Debug.LogWarning($"ApplyBlobAssetReferencePatches<{component}>({packedEntityGuids[packedComponent.PackedEntityIndex]}) but entity to patch does not exist."); } else if (!entityManager.HasComponent(entity, component)) { Debug.LogWarning($"ApplyBlobAssetReferencePatches<{component}>({packedEntityGuids[packedComponent.PackedEntityIndex]}) but component in entity to patch does not exist."); } else { if (component.IsBuffer) { var pointer = (byte *)entityManager.GetBufferRawRW(entity, component.TypeIndex); UnsafeUtility.MemCpy(pointer + targetOffset, &targetBlobAssetReferenceData, sizeof(BlobAssetReferenceData)); } #if !NET_DOTS else if (component.IsManagedComponent) { var obj = entityManager.GetManagedComponentDataAsObject(entity, component); var pointer = (byte *)UnsafeUtility.PinGCObjectAndGetAddress(obj, out ulong handle); pointer += TypeManager.ObjectOffset; UnsafeUtility.MemCpy(pointer + targetOffset, &targetBlobAssetReferenceData, sizeof(BlobAssetReferenceData)); UnsafeUtility.ReleaseGCObject(handle); } #endif else { var pointer = (byte *)entityManager.GetComponentDataRawRW(entity, component.TypeIndex); UnsafeUtility.MemCpy(pointer + targetOffset, &targetBlobAssetReferenceData, sizeof(BlobAssetReferenceData)); } } }while (packedEntities.TryGetNextValue(out entity, ref iterator)); } } // Workaround to catch some special cases where the memory is never released. (e.g. reloading a scene, toggling live-link on/off). patcherBlobAssetSystem.ReleaseUnusedBlobAssets(); }
static void ApplyBlobAssetChanges( EntityManager entityManager, NativeArray <EntityGuid> packedEntityGuids, NativeMultiHashMap <int, Entity> packedEntities, NativeArray <ComponentType> packedTypes, NativeArray <BlobAssetChange> createdBlobAssets, NativeArray <byte> createdBlobAssetData, NativeArray <ulong> destroyedBlobAssets, NativeArray <BlobAssetReferenceChange> blobAssetReferenceChanges) { if (createdBlobAssets.Length == 0 && blobAssetReferenceChanges.Length == 0) { return; } s_ApplyBlobAssetChangesProfilerMarker.Begin(); var managedObjectBlobAssetReferencePatches = new NativeMultiHashMap <EntityComponentPair, ManagedObjectBlobAssetReferencePatch>(blobAssetReferenceChanges.Length, Allocator.Temp); var patcherBlobAssetSystem = entityManager.World.GetOrCreateSystem <EntityPatcherBlobAssetSystem>(); var blobAssetDataPtr = (byte *)createdBlobAssetData.GetUnsafePtr(); for (var i = 0; i < createdBlobAssets.Length; i++) { if (!patcherBlobAssetSystem.TryGetBlobAsset(createdBlobAssets[i].Hash, out _)) { patcherBlobAssetSystem.AllocateBlobAsset(blobAssetDataPtr, createdBlobAssets[i].Length, createdBlobAssets[i].Hash); } blobAssetDataPtr += createdBlobAssets[i].Length; } for (var i = 0; i < destroyedBlobAssets.Length; i++) { patcherBlobAssetSystem.ReleaseBlobAsset(entityManager, destroyedBlobAssets[i]); } for (var i = 0; i < blobAssetReferenceChanges.Length; i++) { var packedComponent = blobAssetReferenceChanges[i].Component; var component = packedTypes[packedComponent.PackedTypeIndex]; var targetOffset = blobAssetReferenceChanges[i].Offset; BlobAssetReferenceData targetBlobAssetReferenceData; if (patcherBlobAssetSystem.TryGetBlobAsset(blobAssetReferenceChanges[i].Value, out var blobAssetPtr)) { targetBlobAssetReferenceData = new BlobAssetReferenceData { m_Ptr = (byte *)blobAssetPtr.Data }; } if (packedEntities.TryGetFirstValue(packedComponent.PackedEntityIndex, out var entity, out var iterator)) { do { if (!entityManager.Exists(entity)) { Debug.LogWarning($"ApplyBlobAssetReferencePatches<{component}>({packedEntityGuids[packedComponent.PackedEntityIndex]}) but entity to patch does not exist."); } else if (!entityManager.HasComponent(entity, component)) { Debug.LogWarning($"ApplyBlobAssetReferencePatches<{component}>({packedEntityGuids[packedComponent.PackedEntityIndex]}) but component in entity to patch does not exist."); } else { if (component.IsBuffer) { var pointer = (byte *)entityManager.GetBufferRawRW(entity, component.TypeIndex); UnsafeUtility.MemCpy(pointer + targetOffset, &targetBlobAssetReferenceData, sizeof(BlobAssetReferenceData)); } else if (component.IsManagedComponent || component.IsSharedComponent) { managedObjectBlobAssetReferencePatches.Add( new EntityComponentPair { Entity = entity, Component = component }, new ManagedObjectBlobAssetReferencePatch { Id = targetOffset, Target = blobAssetReferenceChanges[i].Value }); } else { var pointer = (byte *)entityManager.GetComponentDataRawRW(entity, component.TypeIndex); UnsafeUtility.MemCpy(pointer + targetOffset, &targetBlobAssetReferenceData, sizeof(BlobAssetReferenceData)); } } }while (packedEntities.TryGetNextValue(out entity, ref iterator)); } } s_ApplyBlobAssetChangesProfilerMarker.End(); #if !UNITY_DOTSRUNTIME var managedObjectPatcher = new ManagedObjectBlobAssetReferencePatcher(patcherBlobAssetSystem); // Apply all managed entity patches using (var keys = managedObjectBlobAssetReferencePatches.GetKeyArray(Allocator.Temp)) { keys.Sort(); var uniqueCount = keys.Unique(); for (var i = 0; i < uniqueCount; i++) { var pair = keys[i]; var patches = managedObjectBlobAssetReferencePatches.GetValuesForKey(pair); if (pair.Component.IsManagedComponent) { var obj = entityManager.GetComponentObject <object>(pair.Entity, pair.Component); managedObjectPatcher.ApplyPatches(ref obj, patches); } else if (pair.Component.IsSharedComponent) { var obj = entityManager.GetSharedComponentData(pair.Entity, pair.Component.TypeIndex); managedObjectPatcher.ApplyPatches(ref obj, patches); entityManager.SetSharedComponentDataBoxedDefaultMustBeNull(pair.Entity, pair.Component.TypeIndex, obj); } patches.Dispose(); } } #endif managedObjectBlobAssetReferencePatches.Dispose(); // Workaround to catch some special cases where the memory is never released. (e.g. reloading a scene, toggling live-link on/off). patcherBlobAssetSystem.ReleaseUnusedBlobAssets(); }