I have a game where my code is designed to be on a single scene so I've implemented a singleton like that:
public class MonoSingleton<T> : MonoBehaviour where T : MonoBehaviour
{
private static bool _applicationIsQuitting;
private static readonly object Locker = new object ();
protected static T Instance;
public static T GetInstance {
get {
if (_applicationIsQuitting) {
return null;
}
lock (Locker) {
if (Instance == null) {
Instance = (T)FindObjectOfType (typeof(T));
if (FindObjectsOfType (typeof(T)).Length > 1) {
Debug.LogWarning ("More than one Singleton of type : " + typeof(T));
return Instance;
}
if (Instance == null) {
var singleton = new GameObject ();
Instance = singleton.AddComponent<T> ();
singleton.name = "(MonoSingleton) " + typeof(T);
DontDestroyOnLoad (singleton);
Debug.Log ("An instance of : " + typeof(T) + " is needed in the scene, so " + singleton +
" was create with DontDestroyOnLoad");
return Instance;
}
Debug.Log ("Using instance already created : " + Instance.gameObject.name);
return Instance;
}
return Instance;
}
}
}
public void OnDestroy ()
{
_applicationIsQuitting = true;
}
#region virtual methods
public virtual void Awake ()
{
Debug.Log ("Awake".ColorMe (Color.green) + " instance of : " + typeof(T));
}
#endregion
}
But now with my game growing, I want to split it into mulitple scenes (easier to do now with Unity 5.3).
I mainly use singleton to manage UI. And for this i've a UI GameObject containing my script for current scenes. So on GameObject Awake it create a reference to my Scrit that i can call with script.GetInstance.
My problem is when i refresh a scene or i use a ui component that is already used in previous loaded scene my GetInstance return null. Is there any way to refresh instance reference in virtual Awake method ?
EDIT:
Obviously OnDestroy()
set _applicationIsQuitting
to true
, so GetInstance
return null
. I've try to set it to false
on Awake()
but it doesn't change anything so I do that :
public static T SetInstance {
set {
Debug.Log (Prefix + ("Updating instance of : " + typeof(T)).ColorMe (Color.yellow));
_applicationIsQuitting = false;
Instance = value;
}
}
and on each class when I awake i do the following :
public override void Awake ()
{
base.Awake ();
myScript.SetInstance = this;
}
I prefer to have separated getter and setter to provide myself mode readability.