Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unity singleton manager classes

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?

like image 842
DeviArt Avatar asked Dec 05 '12 18:12

DeviArt


People also ask

What is singleton class Unity?

Generally speaking, a singleton in Unity is a globally accessible class that exists in the scene, but only once. The idea is that any other script can access the singleton, allowing you to easily connect objects to important parts of the game, such as to the player or to other game systems.

What is Singleton manager?

Singleton pattern lets you write a class, which can only be instantiated once. Singleton pattern is a very useful, yet it's a very simple design pattern. It restricts instantiation outside the class by making constructor private. public class Singleton : MonoBehaviour{ //create an object of Singleton.

How do I stop Singleton in Unity?

Creating well-defined relationships between classes would naturally decrease the need of having a Singleton. Your design must be coherent as much as possible but we all know that. Regardless of that it still can get messy when the code base is getting bigger.


2 Answers

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;         }     } 
like image 89
Kay Avatar answered Sep 21 '22 13:09

Kay


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.)

like image 43
Fattie Avatar answered Sep 22 '22 13:09

Fattie