Singletons - Is it bad practice?

Hi uniteers,
I am interested in discussing about singletons. Is it good or bad practice to use them for unity or does it depends on the circumstances?

One of the things that have fueled our discussion is this thread on stack overflow:
http://stackoverflow.com/questions/137975/what-is-so-bad-about-singletons

Keep in mind that this discussion is not unity related, but singletons in general.

We are not that experienced programmers ourselves, and none of us have actually developed a software outside the unity engine. We therefore believe that Unity is a seperate case, and singletons are actually good practice.

Our personal argument for using singletons in our game is to have a global instance of a monobehaviour. What are your arguments of using singletons in your unity projects?

Well, this discussion has been had several times on here.

Like this one:

1 Like

Hmm, guess I didn’t search hard enough. Thanks o7

I also use Singletons, I actually have a class that I inherit my Singletons from. Because of the nature of ‘unity’, I wanted a way to enforce the singleton in unity, because most patterns out there I see don’t actually enforce blocking the way that unity creates instances of a component/script.

Also, I made a nice little editor script that creates a central GameObject to put singletons on by default (though they can be placed anywhere if you so desire), and manage how each singleton is dealt with on loading of a scene.

The editor reflects out all known singletons, and has a drop down, for simple adding of new singletons to the gameobject.

Singleton:

Singleton Editor:
https://code.google.com/p/spacepuppy-unity-framework/source/browse/trunk/SpacepuppyBaseEditor/Inspectors/SingletonInspector.cs

Is it theoretically bad from an OOP viewpoint? Yes
Is it necessary in certain circumstances to make your code cleaner and intentions clearer? Yes

I am by no means a fan of the singleton design pattern, and can definitely work against you in the component based unity, by limiting your flexibility.

Let me give you a real world problem I myself mulled over, when deciding upon using a singleton. I needed a health / damage manager for my main character, no big issue, there will only ever be one main player so I can just use a singleton and enemies can call said health manager, no need for getcomponent, a messaging system, or any other trickery. Then I realised, that I had planned for the player to jump into the perspective of another character and play as them during parts of the gameplay. A singleton would make this a real pain, and give me a lot less flexibility.

However on the other hand, I know there will be one GUI manager in the game, its the design philosophy I prescribe to in this instance(others may have a different opinion on this point). A singleton would allow me to easily facilitate lots of objects calling different elements on the GUI where they are needed, be it to trigger text to be displayed, or whatever.

To summerise, this is subjective information based on my personal experience. You should decide for yourself is probably the best answer. A simpler game, say on mobile may benefit from the less complex nature of a singleton design pattern widely implemented, whereas if you creating a more complex game, your codebase can turn into a steaming pile of spaghetti code.

2 Likes

The answer is “it depends”

For simple projects with small teams or individuals singletons are great. They allow you to access specific game manager type scripts without having to worry about passing around references. They can make your code simpler and cleaner. I note that this is for game manager type objects only. Anything that belongs to a specific game entity, such as player health, should not be a singleton. Singletons are reserved for things that are truly global in scope (like a Facebook manager), not just things that only exist once.

For large projects with big team singletons are bad. They create all sorts of dependencies (Dependencies are bad). They also create hard to diagnose bugs, because anything can get into your singleton object and play around with it. You are far better off investigating patterns like Service Locator or Dependency Injection.

3 Likes

Singletons are also good for something that may some day have multiple instances, but right now only need one.

I’m curious to see how you would go about implementing this. Based on my knowledge this seems like the worst possible use case for a singleton. I’m keen to increase my knowledge.

2 Likes

I’m not sure what Daniel is talking about.

But I’ve used the Multiton pattern with a default entry:

Which you can easily turn a Singleton into.

Basically the Multiton returns a ‘default’ (or the singleton version) of the multiton if you don’t supply some key, and it supplies the keyed version if you pass in a key. You can think of it as a null key’d entry in the multiton. Then there is 2 ‘getInstance’ methods, one with no parameters to return the default, and one that takes a parameter for a key’d entry.

I do this with my ‘Spawn’ pooling system. A global spawn pool is created for managing all of the pooled objects, but if you need to create a special case spawn pool that exists independent of the primary one, you can (this could be useful for say a scenario like a mid-boss that needs a bunch of projectiles and little extras that aren’t otherwise needed in the rest of the level).

Then any of my spawn point scripts I have have an optional field that references which spawnpool you want. If left blank, it uses the default entry.

You can see here:

using UnityEngine;
using System.Collections.Generic;
using System.Linq;

using com.spacepuppy.Collections;
using com.spacepuppy.Utils;

namespace com.spacepuppy.Spawn
{

    [AddComponentMenu("SpacePuppy/Spawn/Spawn Pool")]
    public class SpawnPool : SPNotifyingComponent, ISerializationCallbackReceiver
    {

        #region Static Multiton Interface

        private static SpawnPool _defaultPool;
        private static UniqueList<SpawnPool> _pools = new UniqueList<SpawnPool>(ObjectReferenceEqualityComparer<SpawnPool>.Default);

        public static SpawnPool DefaultPool
        {
            get
            {
                if (_defaultPool == null) CreatePrimaryPool();
                return _defaultPool;
            }
        }

        public static SpawnPool Pool(int index)
        {
            if (_defaultPool == null) CreatePrimaryPool();
            return (index == 0) ? _defaultPool : _pools[index - 1];
        }

        public static SpawnPool Pool(string name)
        {
            if (_defaultPool != null && _defaultPool.name == name) return _defaultPool;
            return (from p in _pools where p.name == name select p).FirstOrDefault();
        }

        public static int PoolCount { get { return _pools.Count + 1; } }

        private static void CreatePrimaryPool()
        {
            if (_defaultPool != null) return;

            var point = (from p in GameObject.FindObjectsOfType<SpawnPool>() orderby p.name == "Spacepuppy.PrimarySpawnPool" select p).FirstOrDefault();
            if (!Object.ReferenceEquals(point, null))
            {
                _defaultPool = point;
            }
            else
            {
                var go = new GameObject("Spacepuppy.PrimarySpawnPool");
                _defaultPool = go.AddComponent<SpawnPool>();
            }
        }

        #endregion

        #region Fields

        [SerializeField()]
        private List<PrefabCacheOptions> _registeredPrefabs = new List<PrefabCacheOptions>();
        [System.NonSerialized()]
        private Dictionary<GameObject, PrefabCacheOptions> _prefabToCache = new Dictionary<GameObject, PrefabCacheOptions>();

        #endregion

        #region CONSTRUCTOR

        protected override void Awake()
        {
            base.Awake();
            if (!Object.ReferenceEquals(this, _defaultPool))
            {
                _pools.Add(this);
            }
        }

        protected override void Start()
        {
            base.Start();

            foreach (var cache in _registeredPrefabs)
            {
                cache.Load();
            }
        }

        protected override void OnDestroy()
        {
            base.OnDestroy();

            if (Object.ReferenceEquals(this, _defaultPool))
            {
                _defaultPool = null;
            }
            else
            {
                _pools.Remove(this);
            }
        }

        #endregion

... rest of the SpawnPool code omitted.

Note… this doesn’t actually use a hashtable, not sure why I didn’t use a hashtable… eh, that can easily be altered if I feel like it at some point.

I remember reading that somewhere, don’t remember the details however. Googling seems to indicate that for multi-threaded applications, you man need one instance per thread.

You could write a Multiton where the thread is the key.

In .Net the thread id is accessible through a static entry point. Which means you wouldn’t necessarily have to pass in the thread id to get it, but have it where the ‘getInstance’ method bases it off the current thread.

I’ve written these before for things like web services that stores a state based on the client attached.

.Net actually also does thing for certain built in static states. For example the ‘OperationContext’ of a service:

https://msdn.microsoft.com/en-us/library/system.servicemodel.operationcontext(v=vs.110).aspx

Though technically not thread dependent. For a thread dependent one just look at the various static entries of the System.Threading.Thread class:

https://msdn.microsoft.com/en-us/library/system.threading.thread(v=vs.110).aspx

(oh, what’s that, Microsoft themself uses a context oriented multiton pattern? heh)

2 Likes

That’s definitely an example of a bad use case. I wouldn’t like it just on the principle that it means that enemies can damage the player, but can’t damage anything else without having a messaging system that could just as easily target the player anyway. It just seems like a shortcut to build something that needs to be built properly anyway.

That’s probably the worst part about them, that they are appealing shortcuts. Unless you are absolutely certain that there should only be one instance at play, it’s probably better to work around the issue through some other means.

1 Like

Not controversial enough. You should’ve asked whether you should use static methods or singletons. Then it’d be a massacre.

I use the singleton pattern very rarely, simply because it’s very rarr that I absolutely have to enforce only one copy of an object existing. Most of the time when I even consider using one, I manage to come up with a use-case scenario where I might want to be able to have multiple copies, and if I can’t, I guarantee another programmer can.

I look at it like this: if it increases dependency and decreases flexibility (and singletons do both), I need a very specific reason for using it, or I need to find another way.

On the other hand, I use static methods all the time for my factories…

3 Likes

I’m going to stir the pot a little here. I spend a lot of my Unity development time thinking about what is the best approach, what is the right architecture, what would the pros do etc etc. And I never seem to finish many projects.

I’m leaning towards BoredMormon here and will say that for small projects, singletons seem to work well. Many of the experiments in my “Failed Projects” folder have a GameManager, SoundManager, WorldManager and those are the bits that worked :slight_smile: The animation, crappy graphics and lighting are what made me give up.

This is from someone that has spent the last 10 or 15 years writing Windows and 3-tier web apps for a living. I can’t think of a single time I’ve used a singleton in that environment, but in Unity for my simple crappy games, they do work. So don’t get hung up on it; you’ll soon know if it works or not.

My 2c worth.

5 Likes

I don’t quiet understand all arguments given in this thread, could someone elaborate?

Question 1:
Why does using a singleton increase dependency compared to the alternative? Lets imagine we are talking about a manager of some sort. This manager could use a singleton for easier acces. The alternative I see is to take this manager and parse it from class to class. But whats the difference between:

SingletonManager.Instance.MethodInsideManager();

or

SomeClass.MethodInsideClass(Manager someManager);

The latter could also be done through an interface instead, is that where the loosely coupled coding comes in?

Question 2:
Some of you who believes that singletons can be replaced with a better alternative, state that you always can find a possible scenario where you actually want two instances of a given class. But I am not sure how you always can come to such a conclusion. As an example, lets say we implement a Sound Manager, whose sole purpose is to have a reference to all playing audio sources. For me, this would be an ideal case of using a singleton because 1. audio is presented all over in your code, and many different events triggers many different types of sound. An easy reference to this manager is ideal for both easy readable code and also structure. (Thats what I believe). 2. Why would anyone have a second instance of Sound Manager? If the singletons are simple enough, I don’t see why you would have a multitude of those.

2 Likes

Don’t have time to go into all that at the moment, but a quick answer to #2:
You might want some less centralized way of dealing with audio, or at the least could wind up splitting it into different classes. Maybe one for music, one for fx, one for speech. Suddenly your amount of singletons is multiplying. Your dependencies are multiplying. You decide you actually need seperate classes for battle music and non-battle music and dialogue music. Starting to see where this is going?

Designing for scalability from the first will save a lot of time later. If you’re working on an endless runner or something, obviously a singleton sound manager is just fine, but on larger programs you don’t want to have to go back and rewrite code constantly. You want to plan for flexibility and scalability from the first.

2 Likes

Thank you, that was a very straightforward and reasonable example, which even I can understand. Good point.

I don’t quite see your angle on this. Most of the reason I would want a singleton there is that I do only want one instance of a class, especially if I do any amount of mixing on the fly or management of subtitles. This is something that just screams authoritarian control for me.

The point is simply that while you may only want one instance of a class right now, that need can change in the future. It can often be easier to plan for something scalable from the start.

Nothing authoritarian, I’m not saying to never use them, just to consider your use of them carefully. Or else. You do not want to make the Code Mafia angry, do you? That’s some mighty nice code there, be a shame if it were to have an…accident.

2 Likes

I wouldn’t argue the “if you’re on the fence, it’s probably better not to” idea (pretty sure I had actually mentioned something along those lines up there). It’s just that this is one of those areas where I see a singleton being nothing but beneficial, and since I’m unaware of a use case of multiple audio outputs, it’s not like I see an instance where I would absolutely need multiple instances.

If it’s thought out properly, an audio manager shouldn’t even be much of a dependency. Most game code should only interact with it by pushing a file and maybe a message, and it should mostly interact with the Unity API. Better yet because all audio is passed through it, it should make it easier to troubleshoot audio issues by keeping logs.