- Home /
Saving last checkpoint hit when reloading scene - Singletons?
Hi,
I'm making a game where many game objects can be moved about to aid progress through the game level. In order to keep levels from becoming unbeatable, the objects have code to respawn them in their usual location should they fall off the level. I also want them ALL to return to their original location upon the player dieing.
First I used a code which would send a death message to all of the objects upon character death, to trigger all of their respawn codes. However, I think this was a bit too much for Unity, as the program crashed everytime this code triggered.
If you want to see that code, it's in this other question here:
Anyhow, because this method didn't work so well, I want to reload the scene entirely whenever the player dies. However, this means that it won't save the last checkpoint the player has reached (aswell as some other stuff i might want to save), meaning the player will always restart from the beginning, which I don't want to happen. I read elsewhere that I could save these variables to an object with a DontDestroyOnLoad script attached, but that I'd need to turn this object into a singleton. After reading some stuff about singletons, I don't understand how they work. Can anyone help me?
If there's a better way to do this, I'd love to know!
Answer by ckfinite · Mar 28, 2011 at 09:03 PM
To answer your second question, a singleton works by allowing only one instance of an object, and you can only have one in C#, due to the OOP nature of the object. Some example (C# code, .NET style, not thread safe)
class Singleton {
private static Singleton _instance;
//protected only allows initialization from inside this class or it's children
protected Singleton() {
}
public static Singleton Instance {
get {
if (_instance == null)
_instance = new Singleton();
return _instance
}
}
}
You would use this from the outside by Singleton.Instance
. This would only allow one instance of the class singleton. However, This will not work, for the obvious reason that is it written for the traditional execution context, and not the GameObject central one that Unity uses.
For Unity's case, you need something similar, but using GameObjects instead of static variables like what is described in the other thread. What they do there is make a Bootstrap class that does this: if there is a LevelManager object, return it, go away. If not, then make a new one, tell it to not destroy when the level is loaded, return that, then go away. Basically what happens in the getter function above, but using a game object instead of a private instance variable, and DontDestroyOnLoad instead of static.
Let me know if that helps!
I'm afraid I'm still feeling totally confused. I understand most things you just said (what do you mean by 'not thread safe'?), but having read through the code for singletons (in Unity) on other peoples questions, I generally don't understand anything thats going on in them at all. Thanks for the explanation though, it cleared stuff up a little.
No problem, this stuff can be hard for a first time user. The 'not thread safe' thing is not really relevant to Unity, and you should never really run into it, thanks to the Unity system. A singleton is basically a global variable, just stored in a OOP (object oriented program$$anonymous$$g) way. A singleton, in short, is a object that you can only have one of. In a normal language, you use a static variable, and a custom function that gets that variable. What makes a singleton special is two things: First, you cannot make a new instance of that singleton from the outside, (continued in next comment)
and second, that the function that gets a instance of the object will make a new object to return if the aforementioned instance is null. In unity, this is a bit more complicated, since statics are discouraged, and C# is something beginning programmers should really avoid.
How this is done in Unity is rather clever: a static variable is one that never goes away. What else does this? A object with DontDestroyOnLoad set! So ins$$anonymous$$d of using a static variable, you use a object with DontDestroyOnLoad. Unfortunately, we cannot really prevent the object being created from outside the designated function, but that is a subset to the main task. Anyway, what you will do is see if the scene has a instance of scenecontroller in it, then if it does, return that, if not, create a new scenecontroller and return that.
O$$anonymous$$, that seems doable. So it's as simple as having something that doesnt destroy on a new load, and having some code on it that checks if another object with the same name exists. If it does, destroy the new object?