/// <summary> /// Adds the given Game Object to the current simulation and starts running its ISimulatable behaviours /// </summary> /// <param name="gameObject">The Game Object to add to simulation</param> public void AddSpawnedObjectToSimulation(GameObject gameObject) { if (gameObject.transform.parent == null && SimulatedContentRoot != null) { m_SimulationSceneModule.AddContentGameObject(gameObject); gameObject.transform.SetParent(SimulatedContentRoot.transform, true); gameObject.SetHideFlagsRecursively(SimulatedObjectHideFlags); } k_Subscribers.Clear(); gameObject.GetComponentsInChildren(k_Subscribers); m_QuerySimulationModule.functionalityIsland.InjectPreparedFunctionality(k_Subscribers); // Because GameObjects may be created in Awake, AddSpawnedObjectToSimulation can be called recursively, thus // we cannot re-use the list of simulatables as it may be modified while iterating var simulatablesList = CollectionPool <List <ISimulatable>, ISimulatable> .GetCollection(); gameObject.GetComponentsInChildren(simulatablesList); foreach (var simulatable in simulatablesList.Cast <MonoBehaviour>()) { m_SpawnedSimulatableBehaviours.Add(simulatable); simulatable.StartRunInEditMode(); } m_SpawnedSimulatableObjects.Add(gameObject); CollectionPool <List <ISimulatable>, ISimulatable> .RecycleCollection(simulatablesList); }
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); }