In projects that feature several singleton classes (as is often the case), it can be clean and convenient to abstract the singleton behaviour to a base class:
using UnityEngine;
using System.Collections.Generic;
using System;
public abstract class MonoBehaviourSingleton<T> : MonoBehaviour {
private static Dictionary<Type, object> _singletons
= new Dictionary<Type, object>();
public static T Instance {
get {
return (T)_singletons[typeof(T)];
}
}
void OnEnable() {
if (_singletons.ContainsKey(GetType())) {
Destroy(this);
} else {
_singletons.Add(GetType(), this);
DontDestroyOnLoad(this);
}
}
}
A MonoBehaviour may then implement the singleton pattern by extending MonoBehaviourSingleton. This approach allows the pattern to be utilised with a minimal footprint on the Singleton itself:
using UnityEngine;
using System.Collections;
public class SingletonImplementation : MonoBehaviourSingleton<SingletonImplementation> {
public string Text= "String Instance";
// Use this for initialisation
IEnumerator Start () {
var demonstration = "SingletonImplementation.Start()\n" +
"Note that the this text logs only once and\n"
"only one class instance is allowed to exist.";
Debug.Log(demonstration);
yield return new WaitForSeconds(2f);
var secondInstance = new GameObject();
secondInstance.AddComponent<SingletonImplementation>();
}
}
Note that one of the benefits of the singleton pattern is that a reference to the instance may be accessed statically:
// Logs: String Instance
Debug.Log(SingletonImplementation.Instance.Text);
Keep in mind though, this practise should be minimised in order to reduce coupling. This approach also comes at a slight performance cost due to the use of Dictionary, but as this collection may contain only one instance of each singleton class, the trade-off in terms of the DRY principle (Don't Repeat Yourself), readability and convenience is small.