##Singleton
The singleton pattern is a very common way to share data and methods across classes in Unity. This code provides an easy-to-use implementation of this pattern that satisfies three goals:
- Minimal clutter in singleton classes: All a singleton need do is derive from Singleton rather than MonoBehaviour, and then call base.onAwake() in its Awake() method.
- Supports both lazy and explicit instantiation: When a singleton is referenced, if it already exists that instance is used; if it doesn't exist, a new instance is created.
- Supports both global and scene-level singletons: Usually you want your singletons to persist across scene changes, but sometimes you want a singleton to be flushed out of memory when a new scene is loaded. Both options are available with this system.
- Derive your singleton component from
Singleton<T>
rather thanMonoBehaviour
. Replace theT
with the name of your class. - You must call
onAwake()
in your component'sAwake()
method. - [Optional] If you want your component to be destroyed when a new scene is loaded, you must override
isGlobalScope
to returnfalse
. You must also give it an OnDestroy handler:void OnDestroy() { base.onDestroy(); }
As part of the initialization process, every singleton is renamed with an underscore followed by the name of the class.
When a singleton is lazily instantiated, it is created as the child of a GameObject
at the root named _SingletonManager
, and its name is followed with " [autogenerated]".
If an instance of a singleton is explicitly instantiated while another instance already exists, the new instance is destroyed and a warning is reported. It is thus safe to explicitly instantiate singletons in each of your scenes if desired.
Each singleton is accessed via ClassName.Instance
. For the convenience your callers, you might want to create static methods and properties of your singletons. Just have such methods reference ClassName.Instance
internally. Because of lazy instantiation, this property will never return null, unless something unrecoverably disastrous has happened.
using UnityEngine;
using System.Collections;
public class YourSingletonClass : Singleton<YourSingletonClass>
{
void Awake()
{
// You MUST call the base class onAwake() method
// before you exit Awake().
onAwake();
}
public bool SomeOtherClassExistsNow = false;
public float Scale = 0.5f;
public void static SetScale(GameObject target)
{
target.transform.localScale = Vector3.one * YourSingletonClass.Instance.Scale;
}
}
using UnityEngine;
using System.Collections;
public class SomeOtherClass : MonoBehaviour
{
void Start()
{
YourSingletonClass.Instance.SomeOtherClassExistsNow = true;
YourSingletonClass.SetScale(gameObject);
}
}
This code includes a couple of existing singletons, both as an example of usage and to provide services that the singleton system itself needs.
DebugManager
: Wraps access to Unity'sDebug.Log()
method, to simply string formatting and to allow logging to be disabled in release builds.GlobalsManager
: A simple class for storing global variables, such as config settings.
The basic trick of this code, the "self-referential generic class", comes from the terrific article, "50 Tips for Working with Unity" by Herman Tulleken.