Tired of waiting for Unity to reload script assemblies every time you run your game? You can turn that off:
@peterdrake Except then static variables persist between sessions, which can easily break poorly-implemented singleton patterns. Be *very* careful.
If your builds are taking a long time, I highly recommend letting unity refresh the Library folder (just close Unity, delete the library folder from your project, and re-open unity). It'll take Unity a while to rebuild that folder, but then script builds should be *much* faster for a while.
@LouisIngenthron Can you say more about properly implementing singletons? A web search reveals a deep rabbit hole on this, but all of them use static variables.
@peterdrake Oh, you still have to use statics, you just have to be smart about it. This is the pattern I use that hasn't failed yet. Put it in the Start() function of MonoBehaviours. Try to avoid singletons of non-unity-managed-objects (you'd need a different pattern than the below).
if(Singleton == null)
{
Singleton = this;
DontDestroyOnLoad(gameObject);
}
else if(Singleton != this)
{
Destroy(gameObject); // two in scene
}
As long as you do that for Unity objects, that first null check will use Unity's override == check to also check for destroyed or unreferenceable objects.
And then in the Destroy function:
if(Singleton != null && Singleton == this)
{
Singleton = null;
}
@peterdrake On 1, correct. That's why I usually make the singleton property a public get but a private set. With the pattern above, that achieves the same goals.
On 2, it's to specifically use Unity's overloaded null checks to make sure it's not pointing to a dead/destroyed reference before checking equality. I'm not sure if the straight equality check does that, so I added a null check as a short-circuit.
@peterdrake No, I don't think so. It would only be to check if a singleton from a previous execution context was still stored in the static reference.
But it's worth noting that there are a number of places where OnDestroy may *not* be called (mostly in-editor, not in-built-game, such as hard exits).
@LouisIngenthron I've almost got it, but can you walk me through a situation where
Singleton != null && Singleton == this
has a different value from:
Singleton == this
@peterdrake It shouldn't, so long as unity's implementation of (Singleton == this) has its own null-check first, which it probably does, but I'm not sure.
So, the situation I'm concerned about would be that Singleton references a destroyed object. Running (Singleton == null) checks if it's null *or* destroyed, which prevents the second check. But I don't know if (Singleton == this) will also break out if it's null or if it will try to run a comparison op between a live object and a destroyed one (which would throw an error).
In other words, it's mostly just me being paranoid and defensively coding.
@LouisIngenthron Ah, I get it. Thanks!
@LouisIngenthron If this was already destroyed, could the Destroy method still run?
It's sort of a race condition, so I'm not sure how to set up a test.