/// <summary>
        /// Removes a set of components from a set of entities defined by a EntityQuery.
        /// </summary>
        /// <remarks>
        /// Removing a component changes an entity's archetype and results in the entity being moved to a different
        /// chunk.
        ///
        /// **Important:** This function creates a sync point, which means that the EntityManager waits for all
        /// currently running Jobs to complete before removing the component 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="entityQuery">The EntityQuery defining the entities to modify.</param>
        /// <param name="types">The types of components to add.</param>
        public void RemoveComponent(EntityQuery entityQuery, ComponentTypes types)
        {
            if (entityQuery.CalculateEntityCount() == 0)
            {
                return;
            }

            // @TODO: Opportunity to do all components in batch on a per chunk basis.
            for (int i = 0; i != types.Length; i++)
            {
                RemoveComponent(entityQuery, types.GetComponentType(i));
            }
        }
        public static T[] ToComponentArray <T>(this EntityQuery group) where T : Component
        {
            int entityCount = group.CalculateEntityCount();
            var arr         = new T[entityCount];

            var iterator           = group.GetArchetypeChunkIterator();
            var indexInEntityQuery = group.GetIndexInEntityQuery(TypeManager.GetTypeIndex <T>());

            var entityCounter = 0;

            while (iterator.MoveNext())
            {
                var chunk = iterator.CurrentArchetypeChunk;
                for (int entityIndex = 0; entityIndex < chunk.Count; ++entityIndex)
                {
                    arr[entityCounter++] = (T)iterator.GetManagedObject(group.ManagedComponentStore, indexInEntityQuery, entityIndex);
                }
            }

            return(arr);
        }
Ejemplo n.º 3
0
        public static T[] ToComponentArray <T>(this EntityQuery group) where T : Component
        {
            int length = group.CalculateEntityCount();
            ComponentChunkIterator iterator = group.GetComponentChunkIterator();
            var indexInComponentGroup       = group.GetIndexInEntityQuery(TypeManager.GetTypeIndex <T>());

            iterator.IndexInEntityQuery = indexInComponentGroup;

            var arr   = new T[length];
            var cache = default(ComponentChunkCache);

            for (int i = 0; i < length; ++i)
            {
                if (i < cache.CachedBeginIndex || i >= cache.CachedEndIndex)
                {
                    iterator.MoveToEntityIndexAndUpdateCache(i, out cache, true);
                }

                arr[i] = (T)iterator.GetManagedObject(group.ManagedComponentStore, cache.CachedBeginIndex, i);
            }

            return(arr);
        }
Ejemplo n.º 4
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
Ejemplo n.º 5
0
        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);
                                }
                        }
        }
Ejemplo n.º 6
0
        protected override void OnUpdate()
        {
            Entity cameraEntity   = default;
            float3 cameraPosition = default;

            if (m_CameraQuery.CalculateEntityCount() > 0)
            {
                cameraEntity = m_CameraQuery.GetSingletonEntity();
                var cameraObject = EntityManager.GetComponentObject <UnityEngine.Camera>(cameraEntity);
                cameraPosition = cameraObject.transform.position;
            }

            var player = this.GetFirstSelfGamePlayer();

            if (!EntityManager.TryGetComponentData(player, out GameRhythmInputComponent playerCommand))
            {
                Destroy();
                return;
            }

            var cameraState = this.GetComputedCameraState();

            var isWorldSpace = cameraState.StateData.Target != default;

            if (!EntityManager.HasComponent <UnitDescription>(cameraState.StateData.Target))
            {
                isWorldSpace = false;
            }

            var canvasRect = m_Canvas.pixelRect;

            if (isWorldSpace && cameraEntity != default)
            {
                var translation = EntityManager.GetComponentData <Translation>(cameraState.StateData.Target);
                m_Canvas.renderMode           = RenderMode.WorldSpace;
                m_Canvas.transform.position   = new Vector3(translation.Value.x, translation.Value.y + 25 * 0.05f, cameraPosition.z + 10);
                m_Canvas.transform.localScale = Vector3.one * 0.05f;

                var rectTransform = m_Canvas.GetComponent <RectTransform>();
                rectTransform.sizeDelta = new Vector2(100, 100);

                canvasRect.width  = 90;
                canvasRect.height = 105;
            }
            else
            {
                m_Canvas.transform.position = Vector3.zero;
                m_Canvas.renderMode         = RenderMode.ScreenSpaceCamera;
                m_Canvas.worldCamera        = EntityManager.GetComponentObject <UnityEngine.Camera>(cameraEntity);
            }

            var pixelRange = new float2(canvasRect.width, canvasRect.height);

            Entity engine = default;

            if (cameraState.StateData.Target != default)
            {
                engine = PlayerComponentFinder.GetRelativeChild <RhythmEngineDescription>(EntityManager, m_EngineQuery, cameraState.StateData.Target, player);
            }
            else
            {
                engine = PlayerComponentFinder.FromQueryFindPlayerChild(m_EngineQuery, player);
            }

            if (engine == default)
            {
                Destroy();
                return;
            }

            var process  = EntityManager.GetComponentData <RhythmEngineLocalState>(engine);
            var settings = EntityManager.GetComponentData <RhythmEngineSettings>(engine);

            if (!EntityManager.HasComponent <RhythmEngineIsPlaying>(engine) || RhythmEngineUtility.GetFlowBeat(process.Elapsed, settings.BeatInterval) < 0)
            {
                Destroy();
                return;
            }

            var key = 1;

            foreach (var ac in playerCommand.Actions)
            {
                if (!ac.InterFrame.HasBeenPressed(timeSystem.GetReport(player).Active))
                {
                    key++;
                    continue;
                }

                var keyRange = new float2();
                if (key <= 2)
                {
                    if (key == 1)
                    {
                        keyRange.x = -0.35f;
                    }
                    else
                    {
                        keyRange.x = 0.35f;
                    }

                    keyRange.x += Random.Range(-0.025f, 0.025f);
                    keyRange.y  = Random.Range(-0.1f, 0.1f);
                }
                else
                {
                    if (key == 3)
                    {
                        keyRange.y = -0.375f;
                    }
                    else
                    {
                        keyRange.y = 0.375f;
                    }

                    keyRange.y += Random.Range(-0.025f, 0.025f);
                    keyRange.x  = Random.Range(-0.1f, 0.1f);
                }

                keyRange += 0.5f;

                var width  = pixelRange.x * 0.5f;
                var height = pixelRange.y * 0.5f;
                var keyPos = new float2(math.lerp(-width, width, keyRange.x), math.lerp(-height, height, keyRange.y));

                var beGameObject = DrumBackendPools[key].Dequeue();
                using (new SetTemporaryInjectionWorld(World))
                {
                    beGameObject.name = $"BackendPressure (Key: {key})";
                    beGameObject.SetActive(true);
                    beGameObject.transform.SetParent(m_Canvas.transform, false);
                    beGameObject.transform.localScale = m_Canvas.renderMode == RenderMode.WorldSpace
                                                ? Vector3.one * 0.7f
                                                : 0.008f * math.min(width, height) * Vector3.one;
                    beGameObject.transform.localPosition = new Vector3(keyPos.x, keyPos.y, 0);
                    beGameObject.transform.rotation      = Quaternion.Euler(0, 0, Random.Range(-12.5f, 12.5f));
                }

                var backend = beGameObject.GetComponent <UIDrumPressureBackend>();
                backend.OnReset();
                backend.SetTarget(EntityManager);
                backend.SetPresentationFromPool(DrumPresentationPools[key]);

                var prevRand     = backend.rand;
                var absRealScore = math.abs(RhythmEngineUtility.GetScore(process.Elapsed, settings.BeatInterval));

                backend.play    = true;
                backend.key     = key;
                backend.rand    = DrumVariantCount[key];
                backend.perfect = absRealScore <= FlowPressure.Perfect;
                backend.endTime = Time.ElapsedTime + 1;

                var i = 0;
                while (prevRand == DrumVariantCount[key] && i < 3)
                {
                    DrumVariantCount[key] = Random.Range(0, 2);
                    i++;
                }

                key++;
            }

            Entities.ForEach((UIDrumPressureBackend backend) =>
            {
                var presentation = backend.Presentation;
                if (presentation != null)
                {
                    if (backend.play)
                    {
                        var color = presentation.colors[backend.key - 1];
                        color.a   = 1;
                        foreach (var effectImage in presentation.effectImages)
                        {
                            effectImage.color = color;
                        }

                        presentation.drumImage.sprite = presentation.sprites[backend.key - 1];

                        backend.play = false;

                        presentation.animator.SetBool(StrHashPerfect, backend.perfect);
                        presentation.animator.SetInteger(StrHashKey, backend.key);
                        presentation.animator.SetFloat(StrHashVariant, backend.rand);
                        presentation.animator.SetTrigger(StrHashPlay);
                    }

                    presentation.animator.Update(Time.DeltaTime);
                }

                if (backend.endTime > Time.ElapsedTime)
                {
                    return;
                }

                backend.Return(true, true);
            }).WithStructuralChanges().Run();

            return;
        }