Both of those are defective and will fail in specific conditions.
Evolve, move up the chain… try this instead.
If you ever find yourself asking “is this instance null?” then you are working with a defective singleton. Delete it and make one that plays nice with Unity3D.
Some super-simple Singleton examples to take and modify:
Simple Unity3D Singleton (no predefined data):
Unity3D Singleton with a Prefab (or a ScriptableObject) used for predefined data:
These are pure-code solutions, DO NOT put anything into any scene, just access it via .Instance
Alternately you could start one up with a [RuntimeInitializeOnLoad] attribute.
There is never a reason to drag a GameObject into a scene if it will be DontDestroyOnLoad.
If you do:
you may drag it into something else that isn’t DDOL. FAIL
you may drag something else into it that isn’t DDOL. FAIL
Just DO NOT drag anything into a scene that will be marked DontDestroyOnLoad. Just Don’t Do It!
Hi, thank you for the reply. I have a few follow-up questions for clarification.
When you said “Both of those are defective and will fail in specific conditions”, are the specific conditions the two DDOL pitfalls you mentioned or are there other conditions where it will fail?
Also (might be related to/the same as the first question), what’s wrong with asking “if this instance null?”, that’s basically what Unity’s own learning resources ask (and I’m not experienced enough to know the issue with that).
For the singleton you provided, does creating different singletons within the same scene causes any problems? (I created 2 blank simpletons using your SingletonSimple template and it seems to work fine, albeit I’m not doing anything much with them.)
I’m asking because Unity provides a generics version of a singleton that allows for different singletons within the same scene by inheriting from the generic singleton. (From page 70 and page 71 of the design patterns ebook (Level up your code with design patterns and SOLID E-book | Unity). I assume your singleton doesn’t have that problem since it doesn’t destroy itself.
For the “Unity3D Singleton with a Prefab” script you provided, you mentioned an example of a music manager. Is the reason why the music manager would need a prefab because the prefab would store the audio clips?
I considered the effects of Exception, Enter Play Mode Settings, and ExecuteAlways, but as far as I know, I couldn’t see a reason to use “Instance != this”.
It might be a failsafe/foolproof code intended to prepare for extending the code to create a instance as needed.
As a side note, please be aware that initialization in the Awake method depends on the script execution order.
In the example code referenced as this, Instance is initialized in SingletonClass.Awake and then accessed from AnotherClass.Awake.
However, unless the script execution order is explicitly set, AnotherClass.Awake might be called first, leading to a null reference exception.
Its used when singleton components are added into scenes. So when that scene with said singleton reloaded again, the second instance destroys itself so as not to have two instances, or override the previous reference. This is not a good approach though.
Kurt is correct that singletons should not live in any of your scenes. They should generally initialise themselves on demand.
Reason being that you don’t want your DontDestroyOnLoad singleton to be referencing any objects in a scene. Once the scene with the objects that your singleton is referencing gets unloaded, all those references are dead (fake null specifically).
My understanding is that it can be resolved with just the condition “Instance != null” in VersionA.
Or is there a special case where the Awake method of a single instance is called multiple times?
See my section on referencing objects in a scene with singletons.
The bottom line is: You both don’t need a singleton in a scene, and don’t want a singleton in your scenes. So having to code anything to do with singletons existing in scenes and potentially having multiple instances is a waste of time: because you shouldn’t be doing it in the first place.
For singletons that initialise themselves on demand, if they reference objects in a scene, and the scene with the objects that the singleton is referencing gets unloaded, would their references not be dead as well?
On-demand singletons - whether they construct themselves or load themselves - can’t have serialized references to anything in a scene anyway.
You can establish references at runtime, so you do need write your code with this mind. But this way you’re still prevented from referencing anything transient in a scene via the inspector.
Then if I had singletons that did live in my scenes, as long as I didn’t reference any objects via the inspector or via the code, would it be as good as having the singleton initialising themselves on demand then?
Also, if I check that the referenced object isn’t null before doing anything with it, would it avoid the dead references problem?
But at this point there is zero reason for it to live in the scene. You are just opening yourself up to potential problems down the line for no reason.
Right, but what do you do with these dead references then? Having these dead references is a symptom of defective code architecture, so you shouldn’t be having these dead references in the first place.
I think I misunderstood you. I believe I thought by saying “You can establish references at runtime, so you do need write your code with this mind” you were implying to avoid establishing references at runtime (via code).
So do you mean for on-demand singletons, that you should establish references at runtime?
Do singletons need to reference objects? Is it not mostly the other way round where objects just reference singletons?
I more meant to say “you can still end up referencing scene objects via code, but you generally should not be”. In some cases you might, but you have to be aware of the lifetime of the objects that you’re referencing.
See above, but they should generally only be referencing assets. It’s all contextual anyway. NOTHING should hold onto a reference to a singleton (aside from itself). That completely defeats the purpose of one.
Is the purpose of being aware of the lifetime of the objects I’m referencing so that I can set the reference to null before the objects get deleted?
I’m confused on this part now, if you generally shouldn’t be referencing scene objects via code for an on-demand singleton.
Why would there be zero reason for a singleton to live in my scene if I didn’t have object references? Both the on-demand singleton (which generally wouldn’t be referencing scene objects) and the live-scene singleton would have no scene object references.
You may have a singleton where objects subscribe themselves to it. Said objects should then also unsubscribe themselves when they’re unloaded. It shouldn’t be up to the singleton to manage their lifetime.
If it has nothing to do with the scene, why is it in the scene? All it does is open yourself up to potential issues down the line.
We’ve established that:
Singletons should not serialize references to anything in a scene
Nothing should hold onto a reference to a singleton (particularly a serialized reference)
The first one is impossible with an on-demand singleton, and the second is less likely to happen as well. However both mistakes are very easy to do with an in-scene singleton.
If you have it in the scene, you also have to write it to manage the possibility of multiple existing. With an on-demand one, it only has to blip itself into existence.
The point is that there is absolutely zero conceivable advantage to putting it in the scene. Just don’t do it! Write them properly. This is well travelled ground that us more experienced users have already travelled down, and so we’re passing this advice down to you. We’re not just making it up as we go.
So are you referring to events then? (I just assume from the word “subscribe”.) (I’ve read about events briefly but I haven’t used them in Unity yet.)
Also, now I just realized, when I mentioned “objects just reference singletons”, I messed up with the wording. I had meant objects using the instance like with MainManager.Instance or SingletonSimple.Instance.
As for having nothing to do with the scene, if the singleton had a Singleton.Instance being referenced by a script in the scene, the singleton would be used still? (It wouldn’t need to reference objects to be useful.) However, I can envision a scenario where a scene wouldn’t necessarily use the singleton but I just assumed that every scene would have something that used Singleton.Instance.
For an on-demand singleton, why wouldn’t you need to manage the possibility of multiple existing?
Doesn’t what you said above, “is this instance null” within Kurt’s on-demand singleton, managing the possibility of multiple existing?
Not strictly events. It could be that they pass a reference to themselves to the singleton so they may recieve some calls or so the singleton can gleam data from them. They then need to ensure they unregister themselves. Again, lots of contextual stuff here.
That is just accessing the singleton, and again it being in the scene gives you no advantage here.
You need to ask yourself: what advantage are you giving yourself by putting it in the scene? Answer: there is none.
No it only manages the possibility of “have we created the singleton yet?”.
There’s no situation in Kurt’s example where you would have more than one.
I used Kurt’s SingletonSimple code and added a public Color TeamColor;. I put Color test = SingletonSimple.Instance.TeamColor; in the void Start() method of a “PlayerController” script. When I played the game, Kurt’s on-demand singleton appeared right at the beginning.
Would it not be managing the possibility of multiple singletons existing in that instance? (Which would be like how the live-scene singleton uses if (Instance != null) to handles multiple singletons existing when loading another scene again.)
It’s literally just “if there is no singleton, then make the singleton” and nothing else. It only allows the possibility of a singleton instance. There is no instance where there can be more than one.
I’m not sure why this is so difficult to understand.