using UnityEngine;
public class TestBehaviour : MonoBehaviour
{
private void OnDestroy()
{
Debug.Log("OnDestroy() called in other");
}
}
//////////////////////
using UnityEngine;
// TODO: Refactor
[DisallowMultipleComponent]
public abstract class MonoBehaviourSingletonBase<SingletonType> : MonoBehaviour
where SingletonType : MonoBehaviourSingletonBase<SingletonType>
{
private static SingletonType _instance;
public static SingletonType Instance
{
get
{
if (_instance == null)
FindOrTryCreateSingleton();
return _instance;
}
}
public static bool IsAnyInstanceLiving => (_instance != null) || FindFirstObjectByType<SingletonType>(findObjectsInactive: FindObjectsInactive.Include);
public virtual string GameObjectName => typeof(SingletonType).Name;
// Initialize
protected virtual void Awake()
{
if ((_instance != null) && (_instance != this))
{
Debug.LogFormat("Scene.name: {0}, Scene.path: {1}, Scene.handle: {2}, Scene.IsValid(): {3}, Scene.isLoaded: {4}, _instance != null: {5}",
_instance.gameObject.scene.name,
_instance.gameObject.scene.path,
_instance.gameObject.scene.handle,
_instance.gameObject.scene.IsValid(),
_instance.gameObject.scene.isLoaded,
_instance != null);
DestroyImmediate(this.gameObject);
return;
}
_instance = (this as SingletonType);
}
protected static void TryCreateSingleton()
{
if (GameControllerPersistentSingleton.IsQuitting || SceneControllerPersistentSingleton.IsActiveSceneChanging)
throw new System.Exception("Cant create Singleton. You are probably trying to instantiate in OnDestroy() or OnDisable()");
_instance = new GameObject(typeof(SingletonType).Name, typeof(SingletonType)).GetComponent<SingletonType>();
_instance.name = _instance.GameObjectName;
#if UNITY_EDITOR
if (!Application.isPlaying)
_instance.hideFlags = HideFlags.DontSave | HideFlags.NotEditable;
#endif
}
protected static void FindOrTryCreateSingleton()
{
// Try to find
if (_instance == null)
_instance = FindFirstObjectByType<SingletonType>(findObjectsInactive: FindObjectsInactive.Include);
// If still cant find, try to create
if (_instance == null)
TryCreateSingleton();
}
protected static void DestroyAllInstances()
{
foreach (var iteratedInstance in FindObjectsByType<SingletonType>(FindObjectsInactive.Include, sortMode: FindObjectsSortMode.None))
DestroyImmediate(iteratedInstance.gameObject);
}
}
//////////////////////
using System;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.SceneManagement;
public sealed class GameControllerPersistentSingleton : MonoBehaviourSingletonBase<GameControllerPersistentSingleton>
{
[field: NonSerialized]
public static bool IsQuitting { get; private set; }
public static bool IsPaused => (Time.timeScale == 0);
// Initialize
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSplashScreen)]
private static void OnBeforeSplashScreen()
{
SceneManager.activeSceneChanged += OnActiveSceneChanged;
SceneManager.sceneLoaded += OnSceneLoaded;
SceneManager.sceneUnloaded += OnSceneUnloaded;
}
// Update
private static void OnActiveSceneChanged(Scene lastScene, Scene loadedScene)
{
Debug.Log("OnActiveSceneChanged called in GameControllerPersistentSingleton");
// RuntimeInitializeOnLoadMethod wont respect execution order and TryCreateSingleton accesses the SceneControllerPersistentSingleton
SceneControllerPersistentSingleton.OnGameControllerActiveSceneChanged(lastScene, loadedScene);
if (!IsAnyInstanceLiving)
TryCreateSingleton();
}
// Dispose
private void OnApplicationQuit()
{
IsQuitting = true;
}
}
//////////////////////
using UnityEngine;
using UnityEngine.SceneManagement;
// TODO: Refactor
[DefaultExecutionOrder(-1)]
public sealed class SceneControllerPersistentSingleton : MonoBehaviourSingletonBase<SceneControllerPersistentSingleton>
{
public static bool IsActiveSceneChanging { get; private set; }
// Update
public void RestartScene()
{
SceneManager.LoadScene(SceneManager.GetActiveScene().name);
}
public static void OnGameControllerActiveSceneChanged(Scene lastScene, Scene loadedScene)
{
Debug.Log("OnActiveSceneChanged() called in SceneControllerPersistentSingleton");
IsActiveSceneChanging = false;
if (!IsAnyInstanceLiving)
TryCreateSingleton();
}
// Dispose
/*private void OnDisable()
{
Debug.Log("OnDestroy() called in SceneControllerPersistentSingleton");
Debug.Log("IsActiveSceneChanging is true");
IsActiveSceneChanging = true;
}*/
private void OnDestroy()
{
Debug.Log("OnDestroy() called in SceneControllerPersistentSingleton");
Debug.Log("IsActiveSceneChanging is true");
IsActiveSceneChanging = true;
}
}
//////////////////////