コード例 #1
0
        /// <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);
                    }
                }
        }
コード例 #2
0
        /// <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)
        {
#if ENABLE_UNITY_COLLECTIONS_CHECKS
            if (srcEntityManager == null || !srcEntityManager.IsCreated)
            {
                throw new ArgumentNullException(nameof(srcEntityManager));
            }
            if (!IsCreated)
            {
                throw new ArgumentException("This EntityManager has been destroyed");
            }
#endif

            srcEntityManager.CompleteAllJobs();
            CompleteAllJobs();

            using (var srcChunks = srcEntityManager.m_UniversalQueryWithChunks.CreateArchetypeChunkArray(Allocator.TempJob, out var srcChunksJob))
                using (var dstChunks = m_UniversalQueryWithChunks.CreateArchetypeChunkArray(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, m_UniversalQueryWithChunks, archetypeChunkChanges);
                        Unity.Entities.EntityComponentStore.AssertSameEntities(srcEntityManager.EntityComponentStore, EntityComponentStore);
                    }
                }
        }
コード例 #3
0
        protected override void OnDestroyManager()
        {
            base.OnDestroyManager();
            EntityManager.CompleteAllJobs();

            nativeManager.ProcessDisposables(new JobHandle());
            nativeManager.DisposePersistents();
            nativeManager.DisposeTempJobs();
        }
コード例 #4
0
ファイル: EntityDiffer.cs プロジェクト: debuggerpls/pongDOTS
        /// <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)
        {
#if ENABLE_PROFILER || UNITY_EDITOR
            s_GetChangesProfilerMarker.Begin();
#endif
            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.CreateArchetypeChunkArray(Allocator.TempJob, out var srcChunksJob))
                using (var dstChunks = dstEntityQuery.CreateArchetypeChunkArray(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);
                    }

                    // @TODO NET_DOTS does not support JobHandle.CombineDependencies with 3 arguments.
#if NET_DOTS
                    var archetypeChunkChangesJobDependencies = CombineDependencies(srcChunksJob, dstChunksJob, clearMissingReferencesJob);
#else
                    var archetypeChunkChangesJobDependencies = JobHandle.CombineDependencies(srcChunksJob, dstChunksJob, clearMissingReferencesJob);
#endif

                    // 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 srcBlobAssets = GetReferencedBlobAssets(
                                           srcChunks, Allocator.TempJob,
                                           jobHandle: out var srcBlobAssetsJob))
                                    using (var dstBlobAssets = 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,
コード例 #5
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="EntityChanges"/> must be disposed when no longer needed.
        /// </summary>
        /// <remarks>
        /// For performance the <see cref="dstToSrcSequenceNumbers"/> is used to map chunks between the given worlds. If this is not provided, or is empty
        /// the tracker must evaluate all chunks, entities, and component data.
        ///
        /// 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 unsafe EntityChanges GetChanges(
            EntityManager srcEntityManager,
            EntityQuery srcEntityQuery,
            EntityManager dstEntityManager,
            EntityQuery dstEntityQuery,
            TypeInfoStream typeInfoStream,
            EntityManagerDifferOptions options,
            Allocator allocator)
        {
            var changes = new EntityChanges();

            srcEntityManager.CompleteAllJobs();
            dstEntityManager.CompleteAllJobs();

            if (options != EntityManagerDifferOptions.None)
            {
                var includeForwardChangeSet = (options & EntityManagerDifferOptions.IncludeForwardChangeSet) ==
                                              EntityManagerDifferOptions.IncludeForwardChangeSet;
                var includeReverseChangeSet = (options & EntityManagerDifferOptions.IncludeReverseChangeSet) ==
                                              EntityManagerDifferOptions.IncludeReverseChangeSet;
                var fastForwardShadowWorld = (options & EntityManagerDifferOptions.FastForwardShadowWorld) ==
                                             EntityManagerDifferOptions.FastForwardShadowWorld;
                var clearMissingReferences = (options & EntityManagerDifferOptions.ClearMissingReferences) ==
                                             EntityManagerDifferOptions.ClearMissingReferences;
                var validateUniqueEntityGuids = (options & EntityManagerDifferOptions.ValidateUniqueEntityGuid) ==
                                                EntityManagerDifferOptions.ValidateUniqueEntityGuid;

                // Query chunks that should be considered for change tracking.
                using (var srcChunks = srcEntityQuery.CreateArchetypeChunkArray(Allocator.TempJob))
                    using (var dstChunks = dstEntityQuery.CreateArchetypeChunkArray(Allocator.TempJob))
                    {
                        if (clearMissingReferences)
                        {
                            ArchetypeChunkChangeUtility.ClearMissingReferences(srcChunks,
                                                                               srcEntityManager.EntityComponentStore, srcEntityManager.GlobalSystemVersion,
                                                                               typeInfoStream);
                        }

                        // Compare the chunks and get a set of all changed chunks.
                        // @NOTE A modified chunk will appear as destroyed and then created.
                        using (var archetypeChunkChanges = ArchetypeChunkChangeUtility.GetArchetypeChunkChanges(srcChunks, dstChunks, Allocator.TempJob))
                        {
                            // If we have no chunk-level changes then there is no work to be done.
                            if (archetypeChunkChanges.HasChanges)
                            {
                                if (includeForwardChangeSet || includeReverseChangeSet)
                                {
                                    BuildComponentDataToEntityLookupTask <EntityGuid> buildSrcEntityGuidToEntityLookupTask =
                                        default;

                                    try
                                    {
                                        using (var buildSrcEntitiesTask =
                                                   new BuildEntityInChunkWithComponentTask <EntityGuid>(
                                                       archetypeChunkChanges.CreatedSrcChunks, Allocator.TempJob))
                                            using (var buildDstEntitiesTask =
                                                       new BuildEntityInChunkWithComponentTask <EntityGuid>(
                                                           archetypeChunkChanges.DestroyedDstChunks, Allocator.TempJob))
                                            {
                                                var handle = JobHandle.CombineDependencies(buildSrcEntitiesTask.Schedule(),
                                                                                           buildDstEntitiesTask.Schedule());

                                                if (validateUniqueEntityGuids)
                                                {
                                                    // Validation is expensive since we must run over the entire world. This is opt in.
                                                    buildSrcEntityGuidToEntityLookupTask =
                                                        new BuildComponentDataToEntityLookupTask <EntityGuid>(
                                                            srcEntityQuery.CalculateEntityCount(), Allocator.TempJob);
                                                    handle = JobHandle.CombineDependencies(handle,
                                                                                           buildSrcEntityGuidToEntityLookupTask.Schedule(srcChunks));
                                                }

                                                handle.Complete();

                                                if (validateUniqueEntityGuids &&
                                                    TryGetDuplicateComponents(
                                                        buildSrcEntityGuidToEntityLookupTask.GetComponentDataToEntityMap(),
                                                        out var duplicates))
                                                {
                                                    throw new DuplicateEntityGuidException(message:
                                                                                           $"Found {duplicates.Length} {nameof(EntityGuid)} components that are shared by more than one Entity, " +
                                                                                           $"see the {nameof(DuplicateEntityGuidException.DuplicateEntityGuids)} property for more information.")
                                                          {
                                                              DuplicateEntityGuids = duplicates
                                                          };
                                                }

                                                var srcState = new WorldState(
                                                    srcEntityManager,
                                                    buildSrcEntitiesTask.GetEntities()
                                                    );

                                                var dstState = new WorldState(
                                                    dstEntityManager,
                                                    buildDstEntitiesTask.GetEntities()
                                                    );

                                                BuildChangeSetTask buildForwardChangeSetTask = default;
                                                BuildChangeSetTask buildReverseChangeSetTask = default;

                                                try
                                                {
                                                    JobHandle buildForwardChangeSetJob = default;
                                                    JobHandle buildReverseChangeSetJob = default;

                                                    if (includeForwardChangeSet)
                                                    {
                                                        buildForwardChangeSetTask = new BuildChangeSetTask(dstState, srcState,
                                                                                                           typeInfoStream, Allocator.TempJob);
                                                        buildForwardChangeSetJob = buildForwardChangeSetTask.Schedule();
                                                    }

                                                    if (includeReverseChangeSet)
                                                    {
                                                        buildReverseChangeSetTask = new BuildChangeSetTask(srcState, dstState,
                                                                                                           typeInfoStream, Allocator.TempJob);
                                                        buildReverseChangeSetJob = buildReverseChangeSetTask.Schedule();
                                                    }

                                                    JobHandle.CombineDependencies(buildForwardChangeSetJob,
                                                                                  buildReverseChangeSetJob).Complete();

                                                    changes = new EntityChanges(
                                                        includeForwardChangeSet
                                                    ? buildForwardChangeSetTask.GetChangeSet(allocator)
                                                    : default,
                                                        includeReverseChangeSet
                                                    ? buildReverseChangeSetTask.GetChangeSet(allocator)
                                                    : default