/// <summary> /// Destroys all entities described in the <see cref="EntityChangeSet"/> /// </summary> /// <remarks> /// Since building the <see cref="NativeMultiHashMap{TEntityGuidComponent, Entity}"/> the entire world is expensive /// this method will incrementally update the map based on the destroyed entities. /// </remarks> private static unsafe void ApplyDestroyEntities( EntityManager entityManager, EntityChangeSet changeSet, NativeMultiHashMap <int, Entity> packedEntities, NativeMultiHashMap <EntityGuid, Entity> entityGuidToEntity) { for (var i = changeSet.Entities.Length - changeSet.DestroyedEntityCount; i < changeSet.Entities.Length; i++) { if (!packedEntities.TryGetFirstValue(i, out var entity, out var iterator)) { continue; } do { // Perform incremental updates on the entityGuidToEntity map to avoid a full rebuild. // @NOTE We do NOT remove from the `entityToEntityGuid` here since the LinkedEntityGroup removal will need it to map back groups. entityGuidToEntity.Remove(changeSet.Entities[i], entity); if (entityManager.EntityComponentStore->Exists(entity)) { entityManager.DestroyEntity(entity); } else { Debug.LogWarning($"DestroyEntity({entity}) but it does not exist."); } }while (packedEntities.TryGetNextValue(out entity, ref iterator)); } }
public void ApplyChangeSet(EntityChangeSet changes) { using (s_PatchesMarker.Auto()) { EntityManagerPatcherUtility.ApplyChangeSet( m_EntityManager, m_EntityQuery, m_PrefabQuery, m_LinkedEntityGroupQuery, changes); } }
private static void ApplyEntityNames( EntityManager entityManager, EntityChangeSet changeSet, NativeMultiHashMap <int, Entity> packedEntities) { for (var i = 0; i < changeSet.Entities.Length; i++) { if (packedEntities.TryGetFirstValue(i, out var entity, out var it)) { do { entityManager.SetName(entity, changeSet.Names[i].ToString()); } while (packedEntities.TryGetNextValue(out entity, ref it)); } } }
/// <summary> /// Creates all new entities described in the <see cref="EntityChangeSet"/> /// </summary> /// <remarks> /// This method only creates the entities and does not set any data. /// </remarks> private static unsafe void ApplyCreateEntities( EntityManager entityManager, EntityChangeSet changeSet, NativeMultiHashMap <int, Entity> packedEntities) { var types = stackalloc ComponentType[0]; var entityGuidArchetype = entityManager.CreateArchetype(types, 0); using (var entities = new NativeArray <Entity>(changeSet.CreatedEntityCount, Allocator.Temp)) { entityManager.CreateEntity(entityGuidArchetype, entities); for (var i = 0; i < changeSet.CreatedEntityCount; ++i) { packedEntities.Add(i, entities[i]); } } }
public EntityChangeSet GetChangeSet(Allocator allocator) { // IMPORTANT. This can add to the packed collections. It must be done before adding destroyed entities. var sharedComponentDataChanges = GetChangedSharedComponents( m_PackedEntities, m_PackedStableTypeHashes, m_ComponentDataStream.DeferredSharedComponentChanges, m_BeforeState.ManagedComponentStore, m_AfterState.ManagedComponentStore); var entities = m_PackedEntities.List; for (var i = 0; i < m_DestroyedEntities.Length; i++) { entities.Add(m_DestroyedEntities[i].Component); } var names = GetEntityNames(entities, m_CreatedEntities, m_ModifiedEntities, m_DestroyedEntities, m_AfterState.EntityManager, m_BeforeState.EntityManager, allocator); // Allocate and copy in to the results buffers. var result = new EntityChangeSet ( m_CreatedEntities.Length, m_DestroyedEntities.Length, m_PackedEntities.List.ToArray(allocator), m_PackedStableTypeHashes.List.ToArray(allocator), names, m_AddComponents.ToArray(allocator), m_RemoveComponents.ToArray(allocator), m_ComponentDataStream.ComponentDataChanges.ToArray(allocator), m_ComponentDataStream.Payload.ToArray(allocator), m_EntityReference.ToArray(allocator), sharedComponentDataChanges, m_LinkedEntityGroupAdditions.ToArray(allocator), m_LinkedEntityGroupRemovals.ToArray(allocator) ); return(result); }
/// <summary> /// This method will generate lookups into the packed change set. /// /// 1) Maps existing entities in the world to <see cref="EntityChangeSet.Entities"/> /// 2) Maps types in the world to <see cref="EntityChangeSet.TypeHashes"/> /// /// These tables are used by subsequent methods to quickly access the packed data. /// </summary> private static void BuildPackedLookups( EntityChangeSet changeSet, NativeMultiHashMap <EntityGuid, Entity> entityGuidToEntity, NativeMultiHashMap <int, Entity> packedEntities, NativeArray <ComponentType> packedTypes) { var buildPackedEntityLookups = new BuildPackedEntityLookupJob { StartIndex = changeSet.CreatedEntityCount, EntityGuids = changeSet.Entities, EntityGuidToEntity = entityGuidToEntity, PackedEntities = packedEntities.AsParallelWriter() }.Schedule(changeSet.Entities.Length - changeSet.CreatedEntityCount, 64); var buildPackedTypeLookups = new BuildPackedTypeLookupJob { TypeHashes = changeSet.TypeHashes, PackedTypes = packedTypes, }.Schedule(changeSet.TypeHashes.Length, 64); JobHandle.CombineDependencies(buildPackedEntityLookups, buildPackedTypeLookups).Complete(); }
public EntityChanges(EntityChangeSet forwardChangeSet, EntityChangeSet reverseChangeSet) { m_ForwardChangeSet = forwardChangeSet; m_ReverseChangeSet = reverseChangeSet; }
internal static void ApplyChangeSet( EntityManager entityManager, EntityQuery entityQuery, EntityQuery prefabQuery, EntityQuery linkedEntityGroupQuery, EntityChangeSet changeSet) { if (!changeSet.IsCreated) { return; } var entityCount = entityQuery.CalculateEntityCount(); using (var packedEntities = new NativeMultiHashMap <int, Entity>(entityCount, Allocator.TempJob)) using (var packedTypes = new NativeArray <ComponentType>(changeSet.TypeHashes.Length, Allocator.TempJob)) using (var entityGuidToEntity = new NativeMultiHashMap <EntityGuid, Entity>(entityCount, Allocator.TempJob)) using (var entityToEntityGuid = new NativeHashMap <Entity, EntityGuid>(entityQuery.CalculateEntityCount(), Allocator.TempJob)) { BuildEntityLookups( entityManager, entityQuery, entityGuidToEntity, entityToEntityGuid); BuildPackedLookups( changeSet, entityGuidToEntity, packedEntities, packedTypes); ApplyDestroyEntities( entityManager, changeSet, packedEntities, entityGuidToEntity); ApplyCreateEntities( entityManager, changeSet, packedEntities); #if UNITY_EDITOR ApplyEntityNames( entityManager, changeSet, packedEntities); #endif ApplyRemoveComponents( entityManager, changeSet.RemoveComponents, changeSet.Entities, packedEntities, packedTypes); ApplyAddComponents( entityManager, changeSet.AddComponents, changeSet.Entities, packedEntities, packedTypes); ApplySetSharedComponents( entityManager, changeSet.SetSharedComponents, changeSet.Entities, packedEntities, packedTypes); ApplySetComponents( entityManager, changeSet.SetComponents, changeSet.Payload, changeSet.Entities, packedEntities, packedTypes, entityGuidToEntity, entityToEntityGuid); var linkedEntityGroupEntitiesLength = CalculateLinkedEntityGroupEntitiesLength(entityManager, linkedEntityGroupQuery); using (var entityGuidToPrefab = new NativeHashMap <EntityGuid, Entity>(prefabQuery.CalculateEntityCount(), Allocator.TempJob)) using (var entityToLinkedEntityGroupRoot = new NativeHashMap <Entity, Entity>(linkedEntityGroupEntitiesLength, Allocator.TempJob)) { BuildPrefabAndLinkedEntityGroupLookups( entityManager, entityQuery, prefabQuery, linkedEntityGroupQuery, entityGuidToPrefab, entityToLinkedEntityGroupRoot); ApplyLinkedEntityGroupRemovals( entityManager, changeSet.LinkedEntityGroupRemovals, changeSet.Entities, packedEntities, entityGuidToEntity, entityToEntityGuid, entityToLinkedEntityGroupRoot); ApplyLinkedEntityGroupAdditions( entityManager, changeSet.LinkedEntityGroupAdditions, changeSet.Entities, packedEntities, entityGuidToEntity, entityToEntityGuid, entityGuidToPrefab, entityToLinkedEntityGroupRoot); ApplyEntityPatches( entityManager, changeSet.EntityPatches, changeSet.Entities, packedEntities, packedTypes, entityGuidToEntity, entityToEntityGuid, entityGuidToPrefab, entityToLinkedEntityGroupRoot); } } }