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);
                }
            }
Exemplo n.º 2
0
        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);
        }
Exemplo n.º 3
0
        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);
                    }
                }
        }
Exemplo n.º 5
0
        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);
         }
 }
Exemplo n.º 8
0
        // 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);
        }
Exemplo n.º 9
0
        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;
        }
Exemplo n.º 10
0
            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));
        }
Exemplo n.º 12
0
        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);
            }
        }
Exemplo n.º 13
0
 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);
 }
Exemplo n.º 14
0
        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));
        }
Exemplo n.º 15
0
        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));
            }
        }
Exemplo n.º 16
0
        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);
        }
Exemplo n.º 17
0
            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);
                }
            }
Exemplo n.º 18
0
        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();
        }
Exemplo n.º 19
0
            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);
                }
            }
Exemplo n.º 20
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);
        }
Exemplo n.º 21
0
        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);
 }
Exemplo n.º 26
0
        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();
        }
Exemplo n.º 27
0
        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);
        }
Exemplo n.º 28
0
        /// <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));
        }