Created
September 19, 2019 12:52
-
-
Save elumixor/ba90b2b24220c38b6e0189e88ad58f3b to your computer and use it in GitHub Desktop.
Unity MonoBehaviour Singleton, that is persistent and disallowing duplicates
This file contains hidden or 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 UnityEditor; | |
using UnityEngine; | |
namespace Shared.SingletonBehaviour { | |
/// <summary> | |
/// Singleton is not guaranteed to be initialized at OnValidate and Awake | |
/// </summary> | |
/// <typeparam name="T"></typeparam> | |
[ExecuteInEditMode] | |
public class SingletonBehaviour<T> : MonoBehaviour where T : SingletonBehaviour<T> { | |
// ReSharper disable once StaticMemberInGenericType | |
private static readonly object Lock = new object(); | |
private static T instance; | |
private static void AssignInstance() { | |
var instances = FindObjectsOfType<T>(); | |
if (instances.Length > 1) { | |
if (instance == null) { | |
for (var i = 1; i < instances.Length; i++) { | |
Debug.LogWarning( | |
$"[Singleton] Instance '{typeof(T)}' already exists in the scene, removing {instances[i]}"); | |
DestroyImmediate(instances[i].gameObject); | |
} | |
instance = instances[0]; | |
} else { | |
foreach (var i in instances) { | |
if (i != instance) { | |
Debug.LogWarning( | |
$"[Singleton] Instance '{typeof(T)}' already exists in the scene, removing {i}"); | |
DestroyImmediate(i.gameObject); | |
} | |
} | |
} | |
} else if (instances.Length == 1) | |
instance = instances[0]; | |
else | |
instance = new GameObject($"{typeof(T)} (Singleton)").AddComponent<T>(); | |
// todo: #if UNITY_EDITOR... conditional check | |
if (Application.isPlaying) { | |
DontDestroyOnLoad(instance); | |
DontDestroyOnLoad(instance.gameObject); | |
} | |
} | |
// todo: Replace existing singleton behaviour in scene | |
protected virtual void Awake() { | |
lock (Lock) AssignInstance(); | |
} | |
protected static T Instance { | |
get { | |
lock (Lock) { | |
if (instance == null) AssignInstance(); | |
return instance; | |
} | |
} | |
} | |
private void OnDestroy() { | |
lock (Lock) if (instance == this) instance = null; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment