I’m cleaning up company code and removing a lot of ugly unmaintainable code I wrote myself back in the days…
And I decided this time to go with Singletons and avoid anything Static as much as possible, because I’ve had issues with them before and removing them made the code run better. Very complex test cases, but practical test cases none the less.
But I’m really not sure this is a wise decision and I could find no real final word on this.
This is an instance of how I’m handling this issue now. Unless someone need, I won’t get into details of auxiliary implementations as I think they speak for themselves:
public class Manager : Singleton<Manager> {
public string reallyGlobalVar = "whatever";
public Language language;
public Scene scene;
void Awake () {
language = Instance.GetOrAddComponent<Language>();
scene = Instance.GetOrAddComponent<Scene>();
}
void Update () {
if (Input.GetKeyUp("escape")) { // on android, this is the "back button"
InceptionSystem.BroadcastAll("EscapeButton");
}
}
}
public class Language : MonoBehaviour {
public string current;
public string lastLang;
}
It is more inconvenient to call them, always with __*Manager.Instance*__ but at least I think it’s less prone to error and problems.
It really depends on your needs. You should be a little careful about thread safety but the same can be said for Static classes. But here are the big wins for using a Singleton IMHO:
Singleton can implement an interface (Static cannot). This allows you to build contracts that you can use for other Singleton objects or just any other class you want to throw around.
Static classes are lazy-loaded when they are first referenced, but must have an empty static constructor (or one is generated for you). Using the Singleton pattern, you do lots of neat stuff such as creating them with a static initialization method and making them immutable, or however you want to control it. You can also inherit from base classes which you can’t do with Static classes.
Singleton— doesn’t have to be. So you can use your singleton instance but if you want for any reason to create another instance of that same class there’s nothing stopping you from doing so.
Hey Dustin, thanks for the reply! But, damit, I wish I could receive notifications so I’d have replied to you long ago. I’m still struggling with forums settings… Hope it will work next time. I’ve stumbled here serendipitously again. The only way I’ve ever replied to anything on forums.
Anyway…
Yeah, I was thinking more about reason #2 there (lazy-load part, didn’t even ever think about inheritance, which should be a separated point), and just today I got to reason #1 as well. Awesome! Tells me I’m in the right path!
But…
For reason #3, I’m not following what you mean at all. What is “Singleton— doesn’t have to be”? Why would I want to create a second “singleton instance”? Isn’t the name already implying it is single? And if it’s a global var, the whole point of using a singleton, to me, is a kind of abstract way of making global vars in object orientation, in which they simply don’t exist - but I think they should.
To me, a proper oop way of having global vars wouldn’t be singleton, but “application parameter” if that makes any sense. The whole application would be a class, and it would have parameters. So we could call AppName.myVar or Application.myVar rather than Singleton.Instance.myVar.
And then I see a reason why we might want to separate those in groups, as illustrated by my example above. So, if that’s the reasoning for #3, I’d still go with something like Global.Group.myVar (instead of Application just because that’s already used for many other things in Unity).
I guess what I meant is that you can repurpose your class. In your case you’re thinking something like this I believe:
public class SomeClass
{
private static SomeClass _instance;
public SomeClass Instance
{
get
{
if(_instance == null)
_instance = new SomeClass();
return _instance;
}
}
//Private constructor to stop instantiation outside of this class
private SomeClass(){ }
}
Now this gives you a somewhat immutable access to an instance of SomeClass which has a private constructor so it can only instantiate itself through the Instance property and since _instance is static, it’s shared across all implementations. However, you could also implement a singleton from a factory of sorts. So your class would look like this:
public class SomeClass
{
//Your logic here
}
And then you’d have your “Globals” class or whatever you want to call it:
public static class Globals
{
private SomeClass _someClassInstance;
public SomeClass SomeClassInstance
{
if(_someClassInstance == null)
_someClassInstance = new SomeClass();
return _someClassInstance;
}
}
Now Globals.SomeClassInstance is essentially a “singleton” (even though it’s not entirely) and anyone calling Globals.SomeClassInstance will always get the same instance of “SomeClass”… but in this case, SomeClass is also a standard class so if you wanted for any reason to instantiate another instance of it you could. No idea if you’d personally ever have a need to do so, but it’s possible. There are reasons you might want to though… such as if you have a need for serialization, so in your static Globals class, you may want to provide a setter for SomeClassInstance or a method to allow it be populated, so you could deserialize and repopulate it later.
Now you’re talking primarily about using something like Singleton which is one method of doing it using a Generic singleton. Nothing wrong with this approach, but again, you still have the ability to have more than one true instance since your Singleton class still has to be able to call new T();. The benefit with using factory or a static instance method is that you can support parameters in your constructor, where as Singleton is going to expect the Manager class or whatever you pass into it to always have and use a parameterless constructor.
To add to this a bit… if you really want to truly use a Singleton pattern, then you do not want to be creating other instances, but likewise you also don’t want to be doing Singleton. Instead your manager would look something like this, which also uses a lock to prevent multiple threads from creating the object more than once so you don’t end up with references to multiple copies. It also uses a private constructor to prevent it from being instantiated anywhere outside of itself:
public class Manager
{
//Your shared instance
private static Manager _instance = null;
//Lock object used for thread safety
private static object _lock = new object();
private static Manager Instance
{
get
{
lock(_lockObject)
{
if(_instance == null)
_instance = new Manager(); // <-- you could use a private parameterized constructor if you wanted
return _instance;
}
}
}
//Make sure this can't be instantiated directly
private Manager(){ }
}
You can actually use some of the same principles to create immutable classes and/or structs. If you ever want to create objects that you don’t want to allow changes to, you can create a private constructor something like this:
public struct Foo
{
public string SurName { get; private set; }
private Foo() {}
private Foo(string surname)
{
SurName = surname;
}
public static Foo FromSurname(string surname)
{
return new Foo(surname);
}
}
The above allows you to impose some interesting restrictions because you’ve made the constructors private and you’ve made the setter for “SurName” private, so the class cannot be instantiated directly and the property cannot be changed. Anytime you want one you just call:
Foo myFoo = Foo.FromSurname("Bar");
If you have objects, especially value type objects, where you never expect the values to change, this is a handy pattern to use as it can save you some debugging headache down the road, especially if you’re working with other developers who may have unexpectedly modified the values.
I think I see what you mean… Global.SomeClassInstance is indeed a singleton, but SomeClassInstance isn’t. And a Singleton which instantiate classes that aren’t singleton themselves make itself a non-pure singleton, per say. Right? Like I did (actually unintentionally) in my example on the first post.
As for your last paragraph on the first post, well, that took me some time and help from a friend here at work. Thing I got wrong is that “Singleton is a design pattern meant to implement Global Variables into objected oriented paradigm” which isn’t precisely true. I understand now it’s meant to implement a class that will have a single instance. It’s almost like static indeed, but not as much as global vars.
In any case, I made some modifications based on all this. Basically 2 new lines properly commented. See what you think:
public class Manager : Singleton<Manager> {
protected Manager () {} // guarantee this will be always a singleton only - can't use the constructor!
public string reallyGlobalVar = "whatever";
public Language language;
public Scene scene;
void Awake () {
language = Instance.GetOrAddComponent<Language>();
scene = Instance.GetOrAddComponent<Scene>();
}
void Update () {
if (Input.GetKeyUp("escape")) { // on android, this is the "back button"
InceptionSystem.BroadcastAll("EscapeButton");
}
}
}
public class Language : Singleton<Language> {
protected Language () {}
new private static Language Instance { get { return null; } } // prevents calling Instance before Manager's Awake
public string current;
public string lastLang;
}
Finally, for the second post, well, I think the fact I wrote all this so without reading it already shows we’re on the same page!
I’ve use { get; protected set; } quite a lot, it’s a nice trick. And now I’ll be finally cleaning up the wiki singleton with a bit more of confidence, after all these lessons. Thanks!
You got it. There are multiple ways to implement a Singleton, some more “pure” than others, but it doesn’t make the others any more wrong. Just use what fits your scenario best. And “private” vs “protected” is pretty much the same except that “protected” allows classes inheriting from your class to also set the property. In your case where you’re wanting to create a Singleton I would recommend writing that as a sealed class anyway so you won’t be tempted to inherit from it and break your pattern.
Going off topic again… Woooot! After going on Forum Actions → General Setting → Default Thread Subscription Mode and checking my Thread Tools is “Subscribed to this thread” I finally fixed it by unsubscribing then subscribing again! Now I got notified!
Also, feel free to add the Sealed or whatever improvements to the wiki as you wish. It’d be very welcomed.
Just a little critique looking at the documentation:
“Instance” isn’t a keyword, it’s a property used to access the singleton instance.
Also, I see why you can’t use a true pure Singleton pattern… you’re using it to implement a singleton MonoBehavior and in order for it’s methods to be fired automatically, they need to be part of a GameObject, and AddComponent needs to be able to intantiate it.
Yes, I know it isn’t a keyword, that’s why I put it in between quotes when talking about it. But, then again, I’m the worst at writing docs. I’m pretty sure you can do much better. As you can see, the best part on them are the ones I borrowed from you!
I couldn’t figure out any way to make the Generic Singleton a pure pattern indeed. But I think the pattern is as pure as it can get right now, with the little code hacks there. Hopefully.
Hello, I have a question about the wiki code, I didn’t get why is it necessary to do this applicationIsQuitting thing in OnDestroy, I mean when Unity quits, or when you quit your game, everything dies, right? so… how could you call a singleton instance then?
I’m asking because, I’m not sure how would I adopt what I modified out of the wiki code, to use this boolean thing. My modification is simple, if more than one instance is found, destroy all instances and keep one alive:
public class Singleton<T> : MonoBehaviour where T : MonoBehaviour
{
private static object mLock = new object();
private static T mInstance;
public static T Instance
{
get
{
lock (mLock) {
if (mInstance == null) {
// try to find it
T[] instances = FindObjectsOfType(typeof(T)) as T[];
// didn't find shit
if (instances == null) {
var instanceObj = new GameObject("(Singleton) " + typeof(T));
mInstance = instanceObj.AddComponent<T>();
DontDestroyOnLoad(instanceObj); // for preservation of this object through scenes
Debug.Log("[SINGLETON]: An instance of `" + typeof(T) + "` is needed." +
" So gameObject `" + instanceObj.name + "` was created" +
" with `" + typeof(T) + "` component attached to it" +
" and with DontDestroyOnLoad called on it.");
}
else
{
// see if there's more than one, if so, do something about it
if (instances.Length > 1) {
Debug.LogWarning("[SINGLETON]: There is more than one instance of `" +
typeof(T) +
"` in your scene. Destroying all, keeping only one...");
for (int i = 1, len = instances.Length; i < len; i++) {
Destroy(instances[i]);
}
}
else if (instances.Length == 1) Debug.Log("[SINGLETON]: Found only one instance of `" +
typeof(T) +
"` in `" + instances[0].gameObject.name +
"` So singlation successful! :)");
mInstance = instances[0];
}
}
return mInstance;
}
}
}
}
Another question, shouldn’t we add some extra measures in Awake()? Like, making sure we only have one singleton. I mean, what if during at some point at run-time you decided to make a new Singleton?
This isn’t really a true singleton pattern, but it’s as close as you can get with a MonoBehavior. The Application Quitting check just prevents another instance from being created or the original instance from being returned if the application is exiting. Honestly though, I still question the need to rig a MonoBehavior to function like a singleton. It’s still going to create a new instance of the MonoBehavior for each game object but it will use a shared instance. In my opinion, the singleton logic should be keep out of the MonoBehavior itself and the logic should be kept separate into a true singleton implementation that is just used by the MonoBehavior. Then you can prevent it from being instantiated and require a call to .Instance to get it.
Wrong. I also thought that, before implementing that OnDestroy. Unity doesn’t always kills everything when application quits. Not on the Editor, at very least. I think it’s a bug in Unity, but in any case you can make it happen, and it’s ugly. This prevents the ugliness from unwarned people. I’d hope the description there was pretty well explained, but maybe not…
If more than one instance is found, it’s better you get a warning and fix it on the code. There shouldn’t be more than one. I actually have a different implementation from the wiki, and maybe I’ll update the wiki with it eventually… In mine, there is no DontDestroyOnLoad within it, I use it outside when needed. So, I can have a “singleton per scene” if that makes any sense. As Dustin said, though, it’s more pure to leave it as it is right now.
I also have recently added a possibility to create the singleton from a prefab. This makes a lot of sense if you need default values to be assigned somehow within the editor.
And there is no need for such preventive measure in Awake, since it’s already there under get.
@Dustin
This wiki singleton won’t create a new instance for each game object. I think that makes little to no sense. Maybe you were talking about vexe’s one? I’m not sure.
As for making the singleton without MonoBehaviour… I really can’t recall, but I had thought of a good reason to do it so. Maybe it had something to do with controlling initialization order within it. And maybe you’re right and it’s just best to not do it… I gotta start writing more comments!
To expand… even when you destroy a game object, your components aren’t destroyed immediately. They’re just “marked” to be destroyed, and at some point they are cleaned up.
As for the game objects… what I mean is that a new component is created for every game object that accesses the Singleton. If you could just call:
Had to think about this after I replied… I do understand why you would want to do it this way. Because you can’t use generics in a MonoBehavior (for instance it couldn’t be Manager).
I’m still not following. If I call Instance it will only create an instance if _instance is null. Else, it will just access it. How’s that creating anything? Also, I think you left your edit missing some parts of your answer! :-o
And awww, I’d hope I was wrong with using MonoBehaviour… And that removing it would also clean up the Singleton code off the need to have a OnDestroy patch… And it would still work just as good! Sad. But I’m not sure generics was my reasoning… Fuck memory!
OK… you’re scaring me - I just felt the need to use a singleton today, I’ve used it and it made sense to me. It made things cleaner. I liked it. And that generic thing is good as well. I haven’t encountered any problems… I don’t see any reason why not to use it (yet) - However @Dustin: if we try to separate the logic from the monobehaviour, for me, for what I have it’s not simple because then I would have to give my singleton instance all the stuff (the logic that was inside the monobehaviour) it needs to do whatever it should do… and that requires creating extra variables and what not, unless I didn’t fully get how you would go about doing that.
Could you put some light on how is it you will separate the logic from the mono and put it in the singleton?
I remembered now! Coroutines. Can’t use them as singleton if it’s not a monobehaviour. And can’t make multiple inheritance of classes in csharp. There. This, and using prefabs (as just mentioned), to me, are good reasons enough to keep the singleton as MonoBehaviour.
I suppose we could still make an abstract non-monobehaviour singleton, but I think there’s no reason to complicate things. What would be the benefit?
He just want to make the singleton implementation as pure as possible, and abstract away the MonoBehaviour component does make sense for that. But, as explained above, it wouldn’t be practical.
“I suppose we could still make an abstract non-monobehaviour singleton, but I think there’s no reason to complicate things. What would be the benefit?”
I was just doing that now that singleton you wrote works for monobehaviours, but sometimes I guess we require just plain normal singletons for classes that aren’t monobehavious (if singleton suits them)