Created
August 28, 2021 17:37
-
-
Save codeimpossible/06dea8032b54165df539789906fefac0 to your computer and use it in GitHub Desktop.
My own implementation of the Singleton pattern for Unity GameObjects
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using UnityEngine; | |
namespace Noirlib { | |
/// <summary> | |
/// Inherit from this base class to create a singleton. | |
/// e.g. public class MyClassName : NoirSingleton<MyClassName> {} | |
/// </summary> | |
public class NoirSingleton<T> : MonoBehaviour where T : MonoBehaviour { | |
// Check to see if we're about to be destroyed. | |
private static bool _shuttingDown = false; | |
private static object _lock = new object(); | |
private static T _instance; | |
private bool _started = false; | |
public static bool IsAssigned() => _instance != null; | |
/// <summary> | |
/// Access singleton instance through this propriety. | |
/// </summary> | |
public static T Instance { | |
get { | |
if (_shuttingDown) { | |
Debug.LogWarning("[Singleton] Instance '" + typeof(T) + | |
"' already destroyed. Returning null."); | |
return null; | |
} | |
if (_instance == null) { | |
lock (_lock) { | |
// Search for existing instance. | |
_instance = (T)FindObjectOfType(typeof(T), includeInactive: true); | |
// Create new instance if one doesn't already exist. | |
if (_instance == null) { | |
// Need to create a new GameObject to attach the singleton to. | |
var singletonObject = new GameObject(); | |
_instance = singletonObject.AddComponent<T>(); | |
singletonObject.name = typeof(T).ToString() + " (Singleton)"; | |
DontDestroyOnLoad(singletonObject); | |
} | |
} | |
} | |
return _instance; | |
} | |
} | |
private void Awake() { | |
CheckInstance(SingletonAwake); | |
} | |
protected virtual void SingletonAwake() { | |
} | |
private void Start() { | |
// Make instance persistent. | |
_started = true; | |
CheckInstance(SingletonStart); | |
} | |
protected virtual void SingletonStart() { | |
} | |
private void OnApplicationQuit() { | |
_shuttingDown = true; | |
} | |
private void OnDestroy() { | |
// only destroy if we actually received a start message | |
_shuttingDown = _started && true; | |
} | |
private void CheckInstance(Action callback) { | |
if (_instance && _instance != this) { | |
Destroy(this); | |
return; | |
} | |
callback(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment