Unity singleton manager classes
Solution 1
Like always: it depends. I use singletons of both kinds, components attached to GameObject
and standalone classes not derived from MonoBehaviour
. IMO the overall question is how are instances bound to the lifcycle of scenes, game objects, ... And not to forget sometimes it is more convenient to have a component especially referencing other MonoBehaviour
objects is easier and safer.
- There are classes that just need to provide some values like for example a config class that needs to load settings from persistence layer when called. I design theese classes as simple singletons.
- On the other hand some objects need to know when a scene is started i.e.
Start
is called or have to perform actions inUpdate
or other methods. Then I implement them as component and attach them to a game object that survives loading new scenes.
I designed component based singletons (type 2) with two parts: a persistent GameObject
called Main
, which holds all components and a flat singleton (type 1) called MainComponentManager
for managing it. Some demo code:
public class MainComponentManger {
private static MainComponentManger instance;
public static void CreateInstance () {
if (instance == null) {
instance = new MainComponentManger ();
GameObject go = GameObject.Find ("Main");
if (go == null) {
go = new GameObject ("Main");
instance.main = go;
// important: make game object persistent:
Object.DontDestroyOnLoad (go);
}
// trigger instantiation of other singletons
Component c = MenuManager.SharedInstance;
// ...
}
}
GameObject main;
public static MainComponentManger SharedInstance {
get {
if (instance == null) {
CreateInstance ();
}
return instance;
}
}
public static T AddMainComponent <T> () where T : UnityEngine.Component {
T t = SharedInstance.main.GetComponent<T> ();
if (t != null) {
return t;
}
return SharedInstance.main.AddComponent <T> ();
}
Now other singletons that want to register as Main
component just look like:
public class AudioManager : MonoBehaviour {
private static AudioManager instance = null;
public static AudioManager SharedInstance {
get {
if (instance == null) {
instance = MainComponentManger.AddMainComponent<AudioManager> ();
}
return instance;
}
}
Solution 2
Engineers who are new to Unity often don't notice that
you can't have a "singleton" in an ECS system.
It is meaningless.
All you have in Unity is GameObjects, at, XYZ positions. They can have components attached.
It would be like trying to have "a singleton" or "inheritance" in .... Photoshop or Microsoft Word.
Photoshop file - pixels at XY positions
Text editor file - letters at X positions
Unity file - GameObjects at XYZ positions
It is "just that simple".
So, in a game you will have "general" behaviors where there is only "one" of the thing. (So obviously there is only "one sound effects engine" , "one screen", "one scoring system" and so on.) A normal programmer would think of those as "singletons", but Unity just has nothing to do with singletons and no connection to singletons.
So if you have "a tank" or "a tree" of course it's normal you may have dozens of those things. But "the sound effects engine" or "the networking system" are "general, only-one-of-them" systems.
Hence, trivially, in Unity "the sound effects engine" or "the networking system" very simply sits on a game object, and, you (obviously) just have the one of them.
Those "general, only-one-of-them" items just sit on the preload scene.
You absolutely have to have a preload scene anyway, in every Unity project.
(Simple how-to: https://stackoverflow.com/a/35891919/294884 )
In the future Unity will include a "built-in preload scene" - when that day comes this will finally never be discussed again!
(Note - some of the languages you use to compile Components for Unity of course have OO concepts; but Unity itself has no connection to OO at all. Unity is like photoshop. You have "game objects" each at a certain 3D position.)
(Note - in the early days of Unity you'd see attempts at making code, say c#, which creates a game object on the fly, attempts to keep the game object unique, and "attaches itself" to the game object as a component. Apart from being completely bizarre/pointless, just FWIW it's theoretically not possible to ensure uniqueness (actually not even within a single frame). Again, it's moot because in Unity general behaviors just go on the preload scene.)
Solution 3
If this class is just for accessing global variables then you don't really need a singleton pattern for this, or use a GameObject.
Simply create a class with public static members.
public class Globals
{
public static int mStatic1 = 0;
public static float mStatic2 = 0.0f;
// ....etc
}
The other solutions are fine but overkill if all you need is global access to variables.
Solution 4
I wrote a singleton class that makes easy to create singleton objects. Its is a MonoBehaviour script, so you can use the Coroutines. Its based on this Unity Wiki article, and I will add option to create it from Prefab later.
So you don't need to write the Singleton codes. Just download this Singleton.cs Base Class, add it to your project, and create your singleton extending it:
public class MySingleton : Singleton<MySingleton> {
protected MySingleton () {} // Protect the constructor!
public string globalVar;
void Awake () {
Debug.Log("Awoke Singleton Instance: " + gameObject.GetInstanceID());
}
}
Now your MySingleton class is a singleton, and you can call it by Instance:
MySingleton.Instance.globalVar = "A";
Debug.Log ("globalVar: " + MySingleton.Instance.globalVar);
Here is a complete tutorial: http://www.bivis.com.br/2016/05/04/unity-reusable-singleton-tutorial/
DeviArt
Updated on March 29, 2021Comments
-
DeviArt about 3 years
In Unity, whats a good way to create a singleton game manager that can be accessed everywhere as a global class with static variables that will spit the same constant values to every class that pulls those values? And what would be the way to implement it in Unity? Do I have to attach it to a GameObject? Can it just be there in a folder without being in the scene visually?
-
DeviArt over 11 yearsThank you so much for such a thorough and knowledgeable answer. Definitely got more then I expected. Cheers!! I'll gladly vote up this answer as soon as I get 15+ reputation points. :)
-
Kay about 10 years@RobertNoack thanks, I added the declaration. See updated answer.
-
shadow_map almost 10 yearsI don't see why one have to use GameObject types for this. For example, couldn't the member "main" just be a normal container instead, for example a generic List? Also, MainComponentManger.instance is static so it will have application scope, and don't need to be stored by a GameObject with DontDestroyOnLoad set.
-
Kay almost 10 years@MikeMegally Some people consider singletons as an anti-pattern and yes in large projects I would rather avoid them
-
Kay almost 10 years@shadow_map That's what I wrote in the first line: Do not use MonoBehaviour if not necessary. On the other hand some classes need to handle events like OnApplicationPause, start coroutines, ...
-
xpereta about 9 yearsAnswers should not be just links to outside websites.
-
Fattie about 8 yearsregarding schemes to "automatically create a game object and attach a MonoBehavior to it ... automatically". (I guess to ... avoid clicking to create a game object?) What happens if you end up with a couple of game objects, each with the Component in question on it? Even if (for some reason) one tried to pull off the "automatic game object" idea, you would have to attend to a dozen points, such as checking for racetrack, multiples, etc. And really it would have to be an the Editor-script level, if the (totally bizarre) concept is "ensure the developer(s) do not have more than one of thing X".
-
rygo6 about 8 yearsI would actually no longer personally endorse use of singletons in Unity.
-
Fattie about 8 yearsThat's because you ROCK
-
Fattie about 8 yearsTo summarize, the script presented above happens to "make a game object". ie it's a script that saves you the trouble of clicking "new game object". It has no connection to singletons since you can't have a singleton
MonoBehavior
, it's meaningless. -
LITM almost 8 yearsHi UnityQA. I'm sorry but what you've said doesn't make sense to me - it's very possible, and in many projects does actually happen, and is very useful. You obviously have a specific scenario in mind, but if I did want a "true" singleton I most likely wouldn't inherit from MonoBehaviour (which has issues around managing the lifetime of the GameObject .)
-
LITM almost 8 yearsI appreciate the passion in the answer * no sarcasm * but I'm still not sure why you are ranting at me. Like I said, if I do build a Singleton it's probably not going to inherit from MonoBehaviour, but why differentiate Unity(which is just a Framework) from the C# environment (or whatever language)? If I use a static it's a class variable, so there is only one instance of that variable regardless of its use in a MonoBehaviour derived class. This is why it's in the language. End of story.
-
Fattie over 7 yearsAs LITM says "If this class is just for accessing global variables..." of course just do this. In terms of the QA at hand, how do you access "globally-needed" monobehaviours in Unity (example, your sound effects etc); of course you just trivially put them on a preload scene (where else could they possibly be? they have to be loaded first) and marked DDOL
-
FanManPro over 5 yearsLine 2 is very much invalid C# and won't compile.
-
Fattie almost 4 yearsThere's no such thing as a "singleton object" in Unity. The concept is utterly meaningless. A Unity scene is just "game objects" (example, a tree, Lara Croft, one cloud, a tank, etc). The concept of a "singleton" in Unity is completely, totally meaningless.
-
Fattie almost 4 years(Note that as a curiosity, this will, anyway .. create duplicates.)
-
AlexGeorg over 2 yearsJust for future readers: Unity changed this mantra in the meantime with "ScriptableObjects" which are independent of instances.
-
Fattie over 2 years@AlexGeorg to some extent that's true; you can essentially use a S.O. to "hold on to a score" or such. an article for anyone reading... unity.com/how-to/architect-game-code-scriptable-objects (See in that article, there's an arrow to "music system". you cant make a "music system" or an "AI system" or the "networking system" or whatever "in a ScriptableObject". those things would be simple persistent "general behavior" game objects as described in the article linked to in this answer stackoverflow.com/questions/35890932/…