Unity singleton manager classes

30,644

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.

  1. 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.
  2. On the other hand some objects need to know when a scene is started i.e. Start is called or have to perform actions in Update 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/

Share:
30,644
DeviArt
Author by

DeviArt

Updated on March 29, 2021

Comments

  • DeviArt
    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
    DeviArt over 11 years
    Thank 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
    Kay about 10 years
    @RobertNoack thanks, I added the declaration. See updated answer.
  • shadow_map
    shadow_map almost 10 years
    I 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
    Kay almost 10 years
    @MikeMegally Some people consider singletons as an anti-pattern and yes in large projects I would rather avoid them
  • Kay
    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
    xpereta about 9 years
    Answers should not be just links to outside websites.
  • Fattie
    Fattie about 8 years
    regarding 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
    rygo6 about 8 years
    I would actually no longer personally endorse use of singletons in Unity.
  • Fattie
    Fattie about 8 years
    That's because you ROCK
  • Fattie
    Fattie about 8 years
    To 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
    LITM almost 8 years
    Hi 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
    LITM almost 8 years
    I 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
    Fattie over 7 years
    As 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
    FanManPro over 5 years
    Line 2 is very much invalid C# and won't compile.
  • Fattie
    Fattie almost 4 years
    There'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
    Fattie almost 4 years
    (Note that as a curiosity, this will, anyway .. create duplicates.)
  • AlexGeorg
    AlexGeorg over 2 years
    Just for future readers: Unity changed this mantra in the meantime with "ScriptableObjects" which are independent of instances.
  • Fattie
    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/…