I would like to have a single "Game Manager" game object or class that contains numerous parameters and tweens or other functions that would be necessary to access throughout my app across various scenes.
I see this is a common need people voice, and an apparently good script was posted here:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using JetBrains.Annotations;
public abstract class Singleton<T> : Singleton where T : MonoBehaviour {
#region Fields
[CanBeNull]
private static T _instance;
[NotNull]
// ReSharper disable once StaticMemberInGenericType
private static readonly object Lock = new object();
[SerializeField]
private bool _persistent = true;
#endregion
#region Properties
[NotNull]
public static T Instance {
get {
if (Quitting) {
Debug.LogWarning($"[{nameof(Singleton)}<{typeof(T)}>] Instance will not be returned because the application is quitting.");
// ReSharper disable once AssignNullToNotNullAttribute
return null;
}
lock (Lock) {
if (_instance != null)
return _instance;
var instances = FindObjectsOfType<T>();
var count = instances.Length;
if (count > 0) {
if (count == 1)
return _instance = instances[0];
Debug.LogWarning($"[{nameof(Singleton)}<{typeof(T)}>] There should never be more than one {nameof(Singleton)} of type {typeof(T)} in the scene, but {count} were found. The first instance found will be used, and all others will be destroyed.");
for (var i = 1; i < instances.Length; i++)
Destroy(instances[i]);
return _instance = instances[0];
}
Debug.Log($"[{nameof(Singleton)}<{typeof(T)}>] An instance is needed in the scene and no existing instances were found, so a new instance will be created.");
return _instance = new GameObject($"({nameof(Singleton)}){typeof(T)}")
.AddComponent<T>();
}
}
}
#endregion
#region Methods
private void Awake() {
if (_persistent)
DontDestroyOnLoad(gameObject);
OnAwake();
}
protected virtual void OnAwake() { }
#endregion
}
public abstract class Singleton : MonoBehaviour {
#region Properties
public static bool Quitting { get; private set; }
#endregion
#region Methods
private void OnApplicationQuit() {
Quitting = true;
}
#endregion
}
In Unity, how do I correctly implement the singleton pattern?
However, I don't actually understand how to use this or what to do with it.
Do I attach this script to a GameObject? Do I need to attach it to one in each scene? Is the idea to attach it to one GameObject in every scene and then the script will automatically kill any duplicates that accidentally get made? I presume if I just attach it to one GameObject in one scene, then if that scene doesn't load it won't be loaded either.
But if I add it to one GameObject in a dummy scene that only loads once on starting the application and never again, this should work right?
I tried attaching it to a GameObject and it says I can't because it's abstract. So I have no idea what to do.
Further, if I wanted to add to that script public float exampleWidth = 1000.0f;
and then be able to access that from anywhere in my game, where in the script would I be meaning to put it?
Then let's say I'm writing in another script attached to another GameObject and want to access something from this like exampleWidth
how do I write that? How do I get
the gameObject holding this script from another scene? Should I find it on Awake/Start in every scene that needs it somehow?
Ideally I want:
- This singleton object/script should always be running.
- If there is none currently in existence, I need one made.
- It should not be destroyed on switching scenes
The other problem I wonder about with this script is when it checks for duplicates and tries to preserve instances[0]
, how do we know if instances[0]
is the original or the new duplicate? It seems it might be random whether the new duplicate or the old original survives.
If you wanted the old original to always survive, could this be possible? For example, if I started a tween loop in the singleton and I want this tween loop to constantly survive so I can use it smoothly and seamlessly even across scene changes, would this be possible? Or would it be best to like I said attach this to just one GameObject in a dummy scene and load that at start up only once?
Thanks for any ideas.