Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

How can I save variables across levels?

Discussion in 'Scripting' started by Marscaleb, Jun 18, 2014.

  1. Marscaleb

    Marscaleb

    Joined:
    Jan 7, 2014
    Posts:
    973
    Well I'm finally getting to the point where I will need this option.

    How can I retain variables across multiple levels?

    Especially since the way Unity works, the fact that I even have a player is because I added a player to my level. So if I tell the script to load a new scene, and that scene has a player in it, the player will have the stats given to that gameobject.

    How can I retain some particular variables I want to keep? I'm going to want to retain the current number of lives, what weapon I have, my score, etc. Of course, what the variable is is pretty arbitrary; it won't make a difference to how I have to save it.

    Of the top of my head, I imagine I will need some sort of external file. Then I would have my player script (or whatever relevant script) designed to check that external file, read chosen variables from it, and then assign those values to the desired variables within the player. And then when the game is called to load a new level (or reload it because the player died) it will find the required variables and write them to that external file. Which also means it needs to write that file to default values when the game starts.

    But I don't know how to create an external file and write values to it. And that's just an idea anyway, I don't know if there is a better method available in Unity.
     
  2. zaxvax

    zaxvax

    Joined:
    Jun 9, 2012
    Posts:
    220
  3. Marscaleb

    Marscaleb

    Joined:
    Jan 7, 2014
    Posts:
    973
    Whoa. I can preserve the actual player.
    Of course, doing so would require some effort to put the player in the correct location with a new level.
     
  4. GarthSmith

    GarthSmith

    Joined:
    Apr 26, 2012
    Posts:
    1,240
    Game data that only needs to exist for this session, we usually keep in non-monobehaviour C# classes or we use DontDestroyOnLoad.

    Settings can use PlayerPrefs, which is a way to save data between game sessions. We use stuff like this for Music On/Off etc... I don't recommend using PlayerPrefs for saving large amounts of data.
    http://docs.unity3d.com/ScriptReference/PlayerPrefs.html

    For save files and more heavy duty stuff, we use the System.IO namespace with LitJSON to write JSON files to disk. XML is popular too.
    http://msdn.microsoft.com/en-us/library/system.io(v=vs.110).aspx
    http://lbv.github.io/litjson/
     
    Magiichan likes this.
  5. Hunter_W

    Hunter_W

    Joined:
    May 5, 2014
    Posts:
    57
  6. Hunter_W

    Hunter_W

    Joined:
    May 5, 2014
    Posts:
    57
  7. Hunter_W

    Hunter_W

    Joined:
    May 5, 2014
    Posts:
    57

    In reply to not knowing another way in Unity: Use this link. You can access the data straight from the target script!

    Overall: you can use any of the methods above this rely orrrrr theres always this:

    http://www.paladinstudios.com/2013/07/10/how-to-create-an-online-multiplayer-game-with-unity/


    If I were to do this on my computer, me being me, I would make it hard for me, but extremely easy for everyone else.

    I would use a Pearl API to port to the Unity files real-time and gather all of the data that way. I would then sub all of the data to the new script; create an organized matrix and BAM! DONE!
     
    Last edited: Jun 19, 2014
  8. Marscaleb

    Marscaleb

    Joined:
    Jan 7, 2014
    Posts:
    973
    I'm trying to use the Don't Destroy On Load function, but I'm hitting a few problems.

    First of all, I can't seem to find a way to inform the object when a new level has loaded. That's pretty important. How I can I tell the object to make itself right with the world if it doesn't know anything has happened?

    Off the top of my head, I could have this object handle the level loading so it calls its own function each time the level changes or gets reset. But then the whole system is thrown out if I mistakenly have another object call to reload the level. A method to identify when a level has been loaded universally would be much better.

    Second of all, if I ever return to the original scene, I get another one of these objects.
    Right now, I have the title scene with a main menu object. When the game is over, it returns back to the title scene. Now there are two menu objects. I can run the cycle over and over and accumulate menu objects.

    Off the top of my head, I could add a command in the start function that checks to see if another object with this script already exists, and then destroy %this if there is. But there should be a more efficient way to handle it. There probably would be if there was a method to see when a new level is loaded.
     
  9. GarthSmith

    GarthSmith

    Joined:
    Apr 26, 2012
    Posts:
    1,240
    Hello!

    MonoBehaviours receive a message when a level loads. The level index is even provided!
    http://docs.unity3d.com/ScriptReference/MonoBehaviour.OnLevelWasLoaded.html

    As for getting duplicate objects, most of our DontDestroyOnLoad game objects are singletons, which guarantees there will only be one object the entire time. Otherwise we need to check for duplicate objects. Here is some singleton code adapted for MonoBehaviours so you can see how this can be accomplished.
    http://wiki.unity3d.com/index.php/Singleton

    That's pretty much how it goes. In the singleton's case we can just check a static variable, otherwise you should tag the game object, or do a FindObjectsOfType() when the scene loads, or something similar.
     
  10. zaxvax

    zaxvax

    Joined:
    Jun 9, 2012
    Posts:
    220
    Code (CSharp):
    1.  
    2. void OnAwake() {
    3.   GameObject instance = GameObject.Find("GameManager") as GameObject;
    4.   if (instance != null) DestroyImmediate(gameObject);
    5. }
     
  11. Marscaleb

    Marscaleb

    Joined:
    Jan 7, 2014
    Posts:
    973
    Oh, well there we go!
    I don't know why that didn't come up when I did a search for "load" in the documentation, but there it is!

    Thank you very much!

    @zaxvax
    I would have thought that doing a search like that could return the object itself.
    Also, would I really want to use DestoryImmediate? The documentation says to avoid that.
     
  12. zaxvax

    zaxvax

    Joined:
    Jun 9, 2012
    Posts:
    220
    With thing that must exist only as a single copy (like game masters, game managers) you need to destroy them immediately, before new copy made something bad. This is what DestoryImmediate does. Simple Destroy will let object live until the end of frame, so it will have enough time to finish Start, Update, FixedUpdates before object dies.
    DestoryImmediate is there to prevent it. Of course you don't want to use that to destroy bullets, players and so on, this is why you have a warning in docs.