0
\$\begingroup\$

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.

\$\endgroup\$
1
\$\begingroup\$

Problem is that _applicationIsQuitting is a static variable. You, probably, should set it in false on Awake call.

\$\endgroup\$
  • \$\begingroup\$ Thanks, you helped me a lot. And allow me to save a large amout of time ^^ \$\endgroup\$ – Sata Jan 3 '16 at 16:52
  • \$\begingroup\$ Nice to hear it. But be careful with Singletons, they are really dangerous and can make you a lot of problems there and bring painfull headeach. \$\endgroup\$ – Vladislav Kurenkov Jan 3 '16 at 17:00
  • \$\begingroup\$ After some reflection i try to remove this for UI management but so far, i have more than 300 scripts just for UI... \$\endgroup\$ – Sata Jan 3 '16 at 17:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.