Make an asset persist through scene changes without affecting other instances?
Sorry for the stupid question, I'm new to Unity, and programming in general really...
I have a scene currently with 4 locked doors. These doors all share the same script currently.
The problem arises when you unlock one of the doors, and go through it, and return to the scene later on. Currently I'm using a static bool to cause the door to persist through scene changes, so when you return to the scene later on, the door will be open!
However, since all of the doors share the same script currently, they are ALL open when you return to the scene. Is there a way that I can cause each of the doors individually to persist through scene changes, and not be affected by eachother?
Even if someone can just point me in the right direction, I can do the research myself, I just have no idea where to go from here right now.
I'm hoping you guys can help!
Answer by ExamplesAreExamples · Nov 26, 2015 at 12:16 AM
Figure out what options you have for keeping data between scenes. A few that come to mind are:
Static variables
DontDestroyOnLoad(...)
PlayerPrefs (strange, but doable)
Other external persistent data (files, databases, whatever)
I'll just touch on static variables as they are likely the simplest solution, but are not persistent between plays. You can later extend it so you can save state between plays.
Each door has a state - opened or closed. Therefore, each door has to have their own piece of memory to store their own state. A simple static boolean would work only for one door (or rather; for all doors at once - they wouldn't remember their individual state). So, we need to store many booleans. How do we store many booleans? Arrays. Lists. Dictionaries. Pick your favourite container and make it the static variable. This is an improvement, but only marginally so. The problem is that we don't know which door each boolean is for, so each door need a unique identifier of some sort. At first, perhaps you think you can only give them a number such as 0, 1, 2 and so on, but it becomes a little annoying when you start to have doors in different scenes. The doors in scene 2 would continue with 3, 4, 5 and so on. Then you remember you needed yet another door in scene 1, and that becomes 6.
0 - scene 1
1 - scene 1
2 - scene 1
3 - scene 2
4 - scene 2
5 - scene 2
6 - scene 1
Sure, they have a unique id each, but for anything bigger than a couple of scenes with a couple of doors, it'll become frustrating to maintain. So what else is there? Well, each Unity object has an instance id - a unique number. Although, that id might change when you go from scene 1 to scene 2, and then back to scene 1 again - I am not 100% sure on that one. Or, you can create a GUID for each object, save it as a serialized string property, and use the string as a key. Or any other method you want, like making a key like string key = levelName + doorID. As long as it's unique, persistent and easy to use.
Then, you could for example use a static dictionary
static Dictionary<string, bool> allDoorsInGame = new Dictionary<string, bool>();
And you can save the state of the door like:
allDoorsInGame[myUniqueKey] = isOpen;
And load the state of the door like:
allDoorsInGame.TryGetValue(myUniqueKey, out isOpen); // will make all doors start closed, btw
This should be all you have to do, but if you want persistency you also need to save all doors state to some file etc when you close the game, and load it when you open the game.
I can do the research myself, I just have no idea where to go from here right now.
See examples of TryGetValue to figure out how you can allow your doors to start open (if you need 1 special door to start open for instance). There are many different kinds of solutions, but a hint is that TryGetValue return a boolean describing if the key exist in the dictionary.