Global Managers With Generic Singletons

Global state and behavior can be a bit tricky to handle in Unity. RedFrame includes a few low-level systems that must always be accessible, so a robust solution is required. While there is no single solution to the problem, there is one particular approach that I’ve found most elegant. There are many reasons one might need global state: controlling menu logic, building additional engine code on top of Unity, executing coroutines that control simulations across level loads, and so on. By design, all code executed in Unity at runtime must be attached to GameObjects as script components, and GameObjects must exist in the hierarchy of a scene. There is no concept of low-level application code outside of the core Unity engine – there are only objects and their individual behaviors. The most common approach to implementing global managers in Unity is to create a prefab that has all manager scripts attached to it. You may have a music manager, an input manager, and dozens of other manager-like scripts stapled onto a single monolithic “GameManager” object. This prefab object would be included in the scene hierarchy in one of two ways:

  • Include the prefab in all scene files.
  • Include the prefab in the first scene, and call its DontDestroyOnLoad method during Awake, forcing it to survive future level loads.

Other scripts would then find references to these manager scripts during Start through one of a variety of built-in Unity methods, most notably FindWithTag and FindObjectOfType. You’d either find the game manager object in the scene and then drill down into its components to find individual manager scripts, or you’d scrape the entire scene to find manager scripts directly. A slightly more automated and potentially more performant option is to use singletons.

Singleton Pattern

The singleton design pattern facilitates global access to an object while ensuring that only one instance of the object ever exists at any one time. If an instance of the singleton doesn’t exist when it is referenced, it will be instantiated on demand. For most C# applications, this is fairly straightforward to implement. In the following code, the static Instance property may be used to access the global instance of the Singleton class:

C# Singleton

public class Singleton
{
	static Singleton instance;

	public static Singleton Instance {
		get {
			if (instance == null) {
				instance = new Singleton ();
			}
			return instance;
		}
	}
}

Unity unfortunately adds some complication to this approach. All executable code must be attached to GameObjects, so not only must an instance of a singleton object always exist, but it must also exist someplace in the scene. The following Unity singleton implementation will ensure that the script is instantiated in the scene:

Unity Singleton

public class UnitySingleton : MonoBehaviour
{
	static UnitySingleton instance;

	public static UnitySingleton Instance {
		get {
			if (instance == null) {
				instance = FindObjectOfType<UnitySingleton> ();
				if (instance == null) {
					GameObject obj = new GameObject ();
					obj.hideFlags = HideFlags.HideAndDontSave;
					instance = obj.AddComponent<UnitySingleton> ();
				}
			}
			return instance;
		}
	}
}

The above implementation first searches for an instance of the UnitySingleton component in the scene if a reference doesn’t already exist. If it doesn’t find a UnitySingleton component, a hidden GameObject is created and a UnitySingleton component is attached to it. In the event that the UnitySingleton component or its parent GameObject is destroyed, the next call to UnitySingleton.Instance will instantiate a new GameObject and UnitySingleton component. For games that include many manager scripts, it can be a pain to copy and paste this boilerplate code into each new class. By leveraging C#’s support for generic classes, we can create a generic base class for all GameObject-based singletons to inherit from:

Generic Unity Singleton

public class UnitySingleton : MonoBehaviour
	where T : Component
{
	private static T instance;
	public static T Instance {
		get {
			if (instance == null) {
				instance = FindObjectOfType<T> ();
				if (instance == null) {
					GameObject obj = new GameObject ();
					obj.hideFlags = HideFlags.HideAndDontSave;
					instance = obj.AddComponent<T> ();
				}
			}
			return instance;
		}
	}
}

A base class is generally unable to know about any of its sub-classes. This is very problematic when inheriting from a singleton base class – for the sake of example lets call one such sub-class “Manager“. The value of Manager.Instance would be a UnitySingleton object instead of its own sub-type, effectively hiding all of Manager‘s public members. By converting UnitySingleton to a generic class as seen above, we are able to change an inheriting class’s Instance from the base type to the inheriting type. When we declare our Manager class, we must pass its own type to UnityManager<T> as a generic parameter: public class Manager : UnitySingleton<Manager>. That’s it! Simply by inheriting from this special singleton class, we’ve turned Manager into a singleton. There is one remaining issue: persistence. As soon as a new scene is loaded, all singleton objects are destroyed. If these objects are responsible for maintaining state, that state will be lost. While a non-persistent Unity singleton works just fine in many cases, we need to have one additional singleton class in our toolbox:

Persistent Generic Unity Singleton

public class UnitySingletonPersistent : MonoBehaviour
	where T : Component
{
	private static T instance;
	public static T Instance {
		get {
			if (instance == null) {
				instance = FindObjectOfType<T> ();
				if (instance == null) {
					GameObject obj = new GameObject ();
					obj.hideFlags = HideFlags.HideAndDontSave;
					instance = obj.AddComponent<T> ();
				}
			}
			return instance;
		}
	}

	public virtual void Awake ()
	{
		DontDestroyOnLoad (this.gameObject);
		if (instance == null) {
			instance = this as T;
		} else {
			Destroy (gameObject);
		}
	}
}

The preceding code will create an object that persists between levels. Duplicate copies may be instantiated if the singleton had been embedded in multiple scenes, so this code will also destroy any additional copies it finds.

Caveats

There are a few important issues to be aware of with this approach to creating singletons in Unity:

Leaking Singleton Objects

If a MonoBehaviour references a singleton during its OnDestroy or OnDisable while running in the editor, the singleton object that was instantiated at runtime will leak into the scene when playback is stopped. OnDestroy and OnDisable are called by Unity when cleaning up the scene in an attempt to return the scene to its pre-playmode state. If a singleton object is destroyed before another scripts references it through its Instance property, the singleton object will be re-instantiated after Unity expected it to have been permanently destroyed. Unity will warn you of this in very clear language, so keep an eye out for it. One possible solution is to set a boolean flag during OnApplicationQuit that is used to conditionally bypass all singleton references included in OnDestroy and OnDisable.

Execution Order

The order in which objects have their Awake and Start methods called is not predictable by default. Persistent singletons are especially susceptible to execution ordering issues. If multiple copies of a singleton exist in the scene, one may destroy the other copies after those copies have had their Awake methods called. If game state is changed during Awake, this may cause unexpected behavior. As a general rule, Awake should only ever be used to set up the internal state of an object. Any external object communication should occur during Start. Persistent singletons require strict use of this convention.

Conclusion

While singletons are inherently awkward to implement in Unity, they’re often a necessary component of a complex game. Some games may require many dozens of manager scripts, so it makes sense to reduce the amount of duplicated code and standardize on a method for setting up, referencing, and tearing down these managers. A generic singleton base class is one such solution that has served us well, but it is by no means perfect. It is a design pattern that we will continue to iterate on, hopefully discovering solutions that more cleanly integrate with Unity.

Posted in Programming
20 comments on “Global Managers With Generic Singletons
  1. Oliver says:

    Really great post! This will be a huge help in my programming efforts. I had been avoiding the use of managers for the very reason they need to be persistent objects in the scene.

    My approach before had been to apply the managers to the main character whom is obviously ever-present in the game. Any thoughts on keeping managers on the Player instead Singletons?

    • mike says:

      This could certainly work if the game is structured in such a way that the player object is always present and can never be destroyed or recreated, such as through death or save game loading.

      I personally prefer to limit each GameObject to being responsible only for its own behavior, while simply observing or requesting behavior changes in other GameObjects. This convention breaks down with game managers, so I’ve tended to have a “_GameManager” prefab where the underscore separates it from the other “physical” GameObjects in the scene. I sort of implicitly treat it like a special class of GameObject. This feels cleaner and more manageable to me, especially since I can edit the _GameManager object’s parameters on-disk as a prefab without worrying about how it will affect any other objects in the scene.

  2. cesarpo says:

    Nice idea to have a generic class for this!! A little detail I found in your code, is that is missing the after the class name!

    thanks!

  3. cesarpo says:

    I see, your blog has eaten the “greater/lower than” symbols!

    < T >

  4. ATesta says:

    I would be curious to know how you use the Persistent Generic Unity Singleton that you describe in the last code chunk (and really, any of the code to be honest).

    1. If you place a script inheriting from UnitySingletonPersistent on a gameobject, it will destroy itself at runtime because your else statement in the Awake method will ALWAYS fire, even for the first instance. Instance will create itself if it does not exist when you access it in the if statement.

    2. Even if you did get to the if statement code you cannot assign to Instance, perhaps you meant _instance = this as t? If so that doesn’t make a lot of sense to me since again, this script will always create an empty game object and attach itself to it if it does not already exist prior to reaching this bit of code.

    3. As far as I know (and testing has confirmed) there is no generic AddComponent() method that takes 0 arguments. Perhaps you meant AddComponent()? I’m not sure if this does exactly what you want it to either though.

    Am I missing something here or is the code provided incorrect?

    • You’re correct, I’d intended to use the private _instance field in the Awake method since it comes without side effect. This should solve the first two problems that you’ve identified; the instance can be assigned in Awake, and it will not automatically instantiate itself when checking its existence. I’ll correct the code. To be honest, I don’t actually use this particular singleton design in production since RedFrame is built within a single scene file.

      Concerning #3, besides the issue of WordPress still eating my generic parameters, a generic AddComponent actually exists in our project as an extension method. It should so obviously be built-in to Unity that I’d forgotten it was our own code! Extension methods probably warrant their own blog post – they’re great for smoothing over some of Unity’s rough edges.

  5. ATesta says:

    Looks like I had the same problem as cesarpo, wordpress deleted the greater than and less than brackets.

    AddComponent (bracket) T (bracket) ();

  6. Ali Raza says:

    Just Fantastic…..Really enlightening.

  7. Dean says:

    When I enter the UnitySingleton code it works fine in Unity4. When I introduce the generic version by modifying the code to be like the UnitySingleton example, MonoDevelop compiles it fine but Unity is reporting “The class defined in script file named ‘MyGenericSingleton’ does not match the file name!”.
    Has anyone else had this problem?

    • Dean says:

      P.S. I’m very careful that the filename does, in fact, match the filename exactly.

      • Dean says:

        OK, My bonehead. The problem has nothing to do with the filename vs. classname. It’s that you can’t use a Generic Class directly in a GameObject. You need a class that can be instantiated.
        I should have realized what was going on. That’s a pretty strange error message for this problem.

  8. I can’t begin to tell you how helpful this was. I immediately implemented it in my project. Originally I was making it into a prefab that is instanced once, but I find this to be the most tidy approach. I still used a prefab, that way every scene will default to the same variable settings. It’s very important for me to be able to launch from any scene in the game in order to test it.

    I really do think Unity should permit a non-component script that always executes. I understand that they want a component-only architecture to take the developer out of the main game loop, but that fundamental approach causes us to do things like this. Nevertheless… it isn’t a show stopper.

  9. Typos says:

    Your persistent example doesnt compile

    _instance = FindObjectOfType(typeof(T)) as T;
    if (_instance == null)
    {
    var obj = new GameObject {hideFlags = HideFlags.HideAndDontSave};
    _instance = obj.AddComponent(typeof(T)) as T;
    }

    • admin says:

      Thanks, I’ve updated the code and modified it to use Unity’s more modern generic versions of FindObjectOfType and AddComponent.

  10. Vijay Kumar R says:

    Thanks Mate…

  11. sava says:

    “Unity unfortunately adds some complication to this approach. All executable code must be attached to GameObjects, so not only must an instance of a singleton object always exist, but it must also exist someplace in the scene.”

    I’m not sure if this was true in the past, but it isn’t as of today. I’m pretty sure plain old singletons work fine in Unity now. The approach from this post is still really useful for having access to the MonoBehaviour callback within your singleton though.

  12. PanStudent says:

    I get an error in Persistent Generic Unity Singleton

    Assets/UnitySingletonPersistent.cs(4,14): error CS0080: Constraints are not allowed on non-generic declarations

    lines:

    4 public class UnitySingletonPersistent : MonoBehaviour
    5 where T : Component

    How to fix this?

  13. David says:

    I think you have a hangover from C++. A little lesson on OO – if you have self enabled OBJECT ORIENTED entities then you dont need managers. Managers are a thing of the past (last decade bred this bad practice).
    The problem with managers is you end up defining all the functionality in the manager and the Object becomes useless – Unity is designed as proper OO usage. Design your objects to “interact” and operate correctly and managers disappear (this is a design issue not a technical one).
    And if you need state flow – look no further than Monobehaviour it _is_ a FSM, or even better use the Animator. Unity provides a wide array of ways to control your world, dont use archaic C++ patterns that make no sense in an OO env.

    • mike says:

      Hi David – do you have an example you can point me to? I’ve not found a way to divorce myself of managers in Unity (and haven’t ever used C++ so can’t compare). It’s been particularly difficult when interacting with external APIs that require a single instance (e.g. Steamworks, the Oculus API, or the Leap Motion API) which in my experience accounts for the majority of singleton use in Unity. How might such interactions be designed not to rely upon a centralized manager?

2 Pings/Trackbacks for "Global Managers With Generic Singletons"
  1. […] quote from redframe-game.com about Unity’s object-oriented programming and how gamemanagers are typically used.  In […]

Leave a Reply

Your email address will not be published. Required fields are marked *

*