This was originally written in response to this question asked on the Unity scripting forums.
What is a singleton?
A singleton is a software design pattern that guarantees only one instance of an object will exist, and this object is globally accessible. dotnetperls.com has a good C# example. There is also a Unity specific example on the Unity Wiki.
Why are singletons discouraged?
Singletons are generally discouraged for the same reason that global variables are generally discouraged. It is easy to couple classes together and break encapsulation.
Having a public static instance always available means that every other script could make calls to the singleton. If this one singleton class was removed from the project, every other script in the project could possibly require edits. This is the opposite of encapsulation taken to the extreme.
What is the alternative to using singletons?
The alternative would be that some Manager class has responsibility for first initializing the non-singleton class. The Manager would make sure only one instance exists, then pass this instance of the non-singleton to whatever system needs it. The instance is usually passed to whatever systems need it in a constructor or initialization function. Those systems may then take the non-singleton and further pass it down to sub-systems.
Why would a singleton be better?
Sometimes using singletons can actually *de*couple your code. If you singleton is widely used by many many otherwise separated systems, then by having a singleton you can avoid the Manager class described above. You can keep the systems of your game separated/encapsulated from each other without having to “stitch them together” using a Manager class.
Using the alternative Manager technique described above, if you have a lot of things that need to use your class, you might end up making a bunch of managers to take the non-singleton object, then pass it down to other systems with their own managers who might pass the non-singleton object further down to sub-systems with sub-managers… This feels *more* coupled to me, since now these separate systems need both the non-singleton class AND the managers to work properly.
Example: We have an AudioManager singleton that is in charge of playing all sound effects in Adventures of Pip. So many different systems in the game need to play a sound. GUI buttons make clicking noises. Enemies play sounds when they get hit. Items play a collection sound when touched. Yet my GUI code, enemy code, and item code would all be separated from each other except for the fact they all play sounds. A singleton makes sense here so I don’t have to write a manager just to load the AudioManager into all those systems.
Truthfully, if I was making banking software or maybe writing all the code myself, I might ban the use of singletons. The idea of rogue code running from anywhere without explicit initialization makes me feel like I don’t have as much control.
But we make games which have constant design changes, and we work with other coders, so being able to drop in a widely used singleton and just access it is too easy and quick to avoid!