static void TriggerOnTemporalSimulationStart()
        {
#if UNITY_EDITOR
            EditorOnlyEvents.OnTemporalSimulationStart();
#endif
            if (onTemporalSimulationStart != null)
            {
                onTemporalSimulationStart();
            }
        }
        bool TryStartSimulation()
        {
            if (!TraitCodeGenerator.HasGenerated || EditorApplication.isPlayingOrWillChangePlaymode)
            {
                return(false);
            }

            var useExistingData = KeepDataBetweenSimulations;

            KeepDataBetweenSimulations = false;
            m_SimulationRestartNeeded  = false;
            NextSimModeSelection       = SimulationModeSelection.NoModePreference;

            // Make sure the watchdog is up-to-date before we check if the scene has entities or subscribers
            m_SceneWatchdogModule.ExecutePollingTask();
            if (!sceneIsSimulatable)
            {
                CleanupSimulation();
                return(false);
            }

            if (!m_SimulationSceneModule.IsSimulationReady)
            {
                return(false);
            }

            // if this method is null, that means something has tried to start simulation when the database isn't setup
            if (IUsesQueryResultsMethods.RegisterQuery == null)
            {
                return(false);
            }

            var simulationSettings = SimulationSettings.instance;

            if (!simulationSettings.IsSpatialContextAvailable)
            {
                return(false);
            }

            var marsSession = MarsRuntimeUtils.GetMarsSessionInActiveScene();

            if (marsSession == null)
            {
                return(false);
            }

            ProfilerMarkers.TryStartSimulation.Begin(); // only profile after safety checks
            if (MarsDebugSettings.QuerySimulationModuleLogging)
            {
                Debug.Log("Start simulation");
            }

            // Cancel delay calls in case the previous simulation was one-shot. Otherwise we can end up stopping behaviors
            // in the middle of temporal simulation or doubling up on delay calls for one-shot simulation.
            EditorApplication.delayCall -= StopRunningOneShot;
            EditorApplication.delayCall -= DelayStopRunningOneShot;

            BeforeSimulationSetup?.Invoke();

            m_SlowTaskModule.ClearTasks();
            QueryObjectMapping.Map.Clear();
            k_TraitRequirements.Clear();
            k_FunctionalitySubscriberObjects.Clear();
            EditorOnlyEvents.OnSimulationStart(k_FunctionalitySubscriberObjects, k_TraitRequirements);
            m_SimulatedObjectsManager.SetupSimulatables(k_FunctionalitySubscriberObjects);

            simulating = true;

            var providersPreserved = useExistingData;

            if (!useExistingData)
            {
                if (m_SimulationContext.Update(marsSession, k_FunctionalitySubscriberObjects, simulatingTemporal))
                {
                    if (MarsDebugSettings.QuerySimulationModuleLogging)
                    {
                        Debug.Log("Simulation context changed. Recreating providers.");
                    }

                    CleanupProviders();

                    functionalityIsland = simulationSettings.EnvironmentMode == EnvironmentMode.Synthetic && simulatingTemporal ?
                                          m_SimulatedDiscoveryIsland : m_SimulationIsland;

                    providersRoot = new GameObject("Providers");
                    m_SimulationSceneModule.AddContentGameObject(providersRoot);
                    GameObjectUtils.gameObjectInstantiated += OnProviderInstantiated;

                    if (addCustomProviders != null)
                    {
                        addCustomProviders(m_Providers);
                        functionalityIsland.AddProviders(m_Providers);
                    }

                    var subscriberTypes = m_SimulationContext.SceneSubscriberTypes;
                    functionalityIsland.SetupDefaultProviders(subscriberTypes, m_Providers);
                    var definitions = new HashSet <TraitDefinition>();
                    k_TraitRequirements.UnionWith(m_SimulationContext.SceneRequirements);
                    m_ReasoningModule.ExtraTraitRequirements.Clear();
                    m_ReasoningModule.ExtraTraitRequirements.UnionWith(k_TraitRequirements);
                    foreach (var requirement in k_TraitRequirements)
                    {
                        definitions.Add(requirement);
                    }

                    functionalityIsland.RequireProvidersWithDefaultProviders(definitions, m_Providers);
                    functionalityIsland.PrepareFunctionalityForSubscriberTypes(subscriberTypes, m_Providers);

                    ModuleLoaderCore.instance.InjectFunctionalityInModules(functionalityIsland);
                    GameObjectUtils.gameObjectInstantiated -= OnProviderInstantiated;
                    providersRoot.SetHideFlagsRecursively(SimulatedObjectsManager.SimulatedObjectHideFlags);

                    foreach (var provider in m_Providers)
                    {
                        var providerBehaviour = provider as MonoBehaviour;
                        if (providerBehaviour != null)
                        {
                            m_ProviderBehaviours.Add(providerBehaviour);
                        }
                    }

                    foreach (var gameObject in m_ProviderGameObjects)
                    {
                        foreach (var simulatable in gameObject.GetComponentsInChildren <ISimulatable>())
                        {
                            var providerBehaviour = simulatable as MonoBehaviour;
                            if (providerBehaviour != null)
                            {
                                m_ProviderBehaviours.Add(providerBehaviour);
                            }
                        }
                    }
                }
                else
                {
                    providersPreserved = true;
                    StopRunningProviders();
                }
            }

            // When using providers from the last simulation, ensure they stay at the bottom of the hierarchy
            if (providersPreserved)
            {
                providersRoot.transform.SetAsLastSibling();
            }

            this.SetCameraScale(MarsWorldScaleModule.GetWorldScale());

            // Set active island now that providers have been setup
            m_FIModule.SetActiveIsland(functionalityIsland);
            functionalityIsland.InjectFunctionalitySingle(marsSession);
            marsSession.StartRunInEditMode();

            if (!useExistingData)
            {
                // Clear the database and then run providers in edit mode so we start getting data.
                m_Database.Clear();
                foreach (var providerBehaviour in m_ProviderBehaviours)
                {
                    providerBehaviour.StartRunInEditMode();
                }
            }

            m_ReasoningModule.ResetReasoningAPIs();

            // We must also reset the backend's query management state each time, otherwise there is no guarantee that
            // the its collections will be ordered the same way each time, even if the ordering of clients in the scene
            // stays the same. This also ensures its slow tasks are registered using edit mode time rather than play mode time.
            m_QueryBackend.ResetQueryManagement();

            GameObjectUtils.gameObjectInstantiated += m_SimulatedObjectsManager.AddSpawnedObjectToSimulation;
            m_QueryBackend.onQueryMatchFound       += k_OnQueryMatchFound;
            m_QueryBackend.onSetQueryMatchFound    += k_OnSetQueryMatchFound;
            if (simulationSettings.FindAllMatchingDataPerQuery)
            {
                m_QueryBackend.onQueryMatchesFound += k_OnQueryMatchesFound;
            }

            // inject functionality on all copied functionality subscribers
            functionalityIsland.InjectPreparedFunctionality(k_FunctionalitySubscriberObjects);

            GeoLocationModule.instance.AddOrUpdateLocationTrait();

            m_SchedulerModule.ResetTime();
            m_SimulatedObjectsManager.StartRunningSimulatables();

            ProfilerMarkers.TryStartSimulation.End();
            return(true);
        }
Пример #3
0
        void CopySimulatablesToSimulationScene()
        {
            ProfilerMarkers.CopySimulatablesToSimulationScene.Begin();
            // Destroy old copied objects and objects spawned by queries.
            DestroySimulatedObjectsRoot();

            // If anything about the session changes in EnsureRuntimeState, it tries to dirty the simulatable scene
            // which would trigger another simulation. To prevent that we temporarily clear the delegate.
            EditorOnlyDelegates.DirtySimulatableScene = null;
            MARSSession.EnsureRuntimeState();
            EditorOnlyDelegates.DirtySimulatableScene = DirtySimulatableScene;
            var session = MarsRuntimeUtils.GetMarsSessionInActiveScene();

            // Find all the root game objects in the active scene and move them under a root transform.
            var activeScene = SceneManager.GetActiveScene();

            k_RootGameObjects.Clear();
            activeScene.GetRootGameObjects(k_RootGameObjects);
            SimulatedContentRoot = new GameObject(k_TemporaryRootName);
            SimulatedContentRoot.SetActive(false);
            foreach (var gameObject in k_RootGameObjects)
            {
                gameObject.transform.SetParent(SimulatedContentRoot.transform, true);
            }

            k_OriginalSimulatables.Clear();
            SimulatedContentRoot.GetComponentsInChildren(k_OriginalSimulatables);

            k_OriginalTransforms.Clear();
            SimulatedContentRoot.GetComponentsInChildren(k_OriginalTransforms);
            k_OriginalTransforms.RemoveAt(0); // Ignore the root

            // Copy the root transform to the simulated content scene. The reason we copy simulatables this way rather than
            // copying them individually is so that their references to other simulatables stay intact.
            var copiedSimulatedContentRoot = GameObjectUtils.CloneWithHideFlags(SimulatedContentRoot);

            copiedSimulatedContentRoot.name = k_SimulatedContentRootName;

            // After copying, we need to move original gameobjects back to the scene root.
            foreach (var gameObject in k_RootGameObjects)
            {
                gameObject.transform.SetParent(null, true);
            }

            UnityObjectUtils.Destroy(SimulatedContentRoot);
            SimulatedContentRoot = copiedSimulatedContentRoot;

            // Remove the copied MARS Session to avoid conflicts
            var copiedSession = SimulatedContentRoot.GetComponentInChildren(typeof(MARSSession));

            UnityObjectUtils.Destroy(copiedSession);

            m_SimulationSceneModule.AddContentGameObject(SimulatedContentRoot);

            k_CopiedTransforms.Clear();
            SimulatedContentRoot.GetComponentsInChildren(k_CopiedTransforms);
            k_CopiedTransforms.RemoveAt(0); // Ignore the root
            var copiedTransformsCount = k_CopiedTransforms.Count;

            Debug.Assert(k_OriginalTransforms.Count == copiedTransformsCount,
                         "Copied Transforms in the simulation scene do not map 1:1 with original Transforms in the query scene.");

            m_OriginalToCopiedTransforms.Clear();
            m_CopiedToOriginalTransforms.Clear();
            for (var i = 0; i < copiedTransformsCount; ++i)
            {
                AddTransformCopy(k_CopiedTransforms[i], k_OriginalTransforms[i]);
            }

            m_SimulatableBehaviours.Clear();
            k_CopiedSimulatables.Clear();
            SimulatedContentRoot.GetComponentsInChildren(k_CopiedSimulatables);
            var copiedSimulatablesCount = k_CopiedSimulatables.Count;

            Debug.Assert(k_OriginalSimulatables.Count == copiedSimulatablesCount,
                         "Copied ISimulatables in the simulation scene do not map 1:1 with original ISimulatables in the query scene.");

            m_CopiedToOriginalSimulatables.Clear();
            m_OriginalToCopiedSimulatables.Clear();
            m_LandmarkControllers.Clear();
            for (var i = 0; i < copiedSimulatablesCount; i++)
            {
                var originalSimulatable = k_OriginalSimulatables[i];
                var copiedSimulatable   = k_CopiedSimulatables[i];
                var behaviour           = copiedSimulatable as MonoBehaviour;
                if (behaviour != null)
                {
                    m_SimulatableBehaviours.Add(behaviour);
                }

                var landmarkController = originalSimulatable as LandmarkController;
                if (landmarkController)
                {
                    m_LandmarkControllers[landmarkController] = (LandmarkController)copiedSimulatable;
                }

                AddSimulatedCopy(copiedSimulatable, originalSimulatable);
            }

            AddSyntheticEnvironmentSimulatedObjects();

            EditorOnlyEvents.OnSetupSimulatables(m_SimulatableBehaviours);
            k_CopiedLights.Clear();
            SimulatedContentRoot.GetComponentsInChildren(k_CopiedLights);
            // Content scene lights on shouldn't cast on the simulated environment
            foreach (var light in k_CopiedLights)
            {
                light.cullingMask &= ~(SimulationConstants.SimulatedEnvironmentLayerMask);
            }

            // Set up simulation camera at the device starting position
            // with the correct settings for rendering the sim scene
            var cameraReference = session.cameraReference;

            if (cameraReference == null)
            {
                cameraReference = session.GetComponentInChildren <MARSCamera>(true);
                if (cameraReference == null)
                {
                    Debug.LogError("MARSSession does not have a MARSCamera");
                    return;
                }
            }

            var originalCamera    = cameraReference.gameObject;
            var copiedCameraTrans = GetCopiedTransform(originalCamera.transform);

            var startingPose = m_EnvironmentManager.DeviceStartingPose;

            copiedCameraTrans.SetLocalPose(startingPose);
            SimulatedCamera            = copiedCameraTrans.GetComponent <Camera>();
            SimulatedCamera.cameraType = CameraType.SceneView;
            SimulatedCamera.tag        = "Untagged"; // Copied camera should not be marked as the main camera
            SimulationSceneModule.instance.AssignCameraToSimulation(SimulatedCamera);

            // Disallow MSAA on copied camera to avoid tiled GPU perf warning
            // https://issuetracker.unity3d.com/issues/tiled-gpu-perf-warning-appears-when-multiple-cameras-with-allow-msaa-are-present-in-the-scene-and-viewport-rect-is-not-default
            SimulatedCamera.allowMSAA = false;

            SimulatedContentRoot.AddToHideFlagsRecursively(SimulatedObjectHideFlags);

            EntityVisualsModule.instance.simEntitiesRoot = SimulatedContentRoot.transform;
            SimulatedContentRoot.SetActive(true);

            foreach (var contentHierarchy in Resources.FindObjectsOfTypeAll <ContentHierarchyPanel>())
            {
                contentHierarchy.RestoreState();
            }

            ProfilerMarkers.CopySimulatablesToSimulationScene.End();
        }