/// <summary> /// Terminates this DualityApp. This does not end the current Process, but will instruct the engine to /// leave main loop and message processing as soon as possible. /// </summary> public static void Terminate() { if (!initialized) { return; } if (isUpdating) { terminateScheduled = true; return; } if (environment == ExecutionEnvironment.Editor && execContext == ExecutionContext.Game) { Scene.Current.Dispose(); Log.Core.Write("DualityApp terminated in sandbox mode."); terminateScheduled = false; return; } if (execContext != ExecutionContext.Editor) { OnTerminating(); SaveUserData(); } // Signal that the game simulation has ended. if (execContext == ExecutionContext.Game) { pluginManager.InvokeGameEnded(); } // Discard plugin data (Resources, current Scene) ahead of time. Otherwise, it'll get shut down in ClearPlugins, after the backend is gone. pluginManager.DiscardPluginData(); sound.Dispose(); sound = null; ShutdownBackend(ref graphicsBack); ShutdownBackend(ref audioBack); pluginManager.ClearPlugins(); // Since this performs file system operations, it needs to happen before shutting down the system backend. Profile.SaveTextReport(environment == ExecutionEnvironment.Editor ? "perflog_editor.txt" : "perflog.txt"); ShutdownBackend(ref systemBack); // Shut down the plugin manager and plugin loader pluginManager.Terminate(); pluginManager.PluginsReady -= pluginManager_PluginsReady; pluginManager.PluginsRemoving -= pluginManager_PluginsRemoving; pluginManager.PluginsRemoved -= pluginManager_PluginsRemoved; pluginLoader.Terminate(); pluginLoader = null; Log.Core.Write("DualityApp terminated"); initialized = false; execContext = ExecutionContext.Terminated; }