Search Unity

How Save System Works

Discussion in 'Scripting' started by alexxjaz, Jun 26, 2019.

  1. alexxjaz

    alexxjaz

    Joined:
    Sep 18, 2018
    Posts:
    45
    Hello. I recently saw a video of how save and load data but I dont think I undestand it.

    In this video he has a player with some data, so to save it he creates another script where he is going to get again that info.

    The problem is when he creates the save/load system, because in the method he always feed it with this script that he has created, so do I need a different method for each script that I want to save? Or how could I make it work with any script?

    This is the video:


    The SaveSystem code:
    Code (CSharp):
    1.     public static void SavePlayer (PlayerController playerController)
    2.     {
    3.         BinaryFormatter formatter = new BinaryFormatter();
    4.         //Guardamos en un path
    5.         string path = Application.persistentDataPath + "player.data";
    6.         FileStream stream = new FileStream(path, FileMode.Create);
    7.  
    8.         Player01Data data = new Player01Data(playerController);
    9.  
    10.         formatter.Serialize(stream, data);
    11.         stream.Close();
    12.     }
    13.  
    14.     public static Player01Data LoadPlayer()
    15.     {
    16.         string path = Application.persistentDataPath + "player.data";
    17.         //Comprobamos si el archivo existe
    18.         if (File.Exists(path))
    19.         {
    20.             BinaryFormatter formatter = new BinaryFormatter();
    21.             FileStream stream = new FileStream(path, FileMode.Open);
    22.  
    23.             Player01Data data = formatter.Deserialize(stream) as Player01Data;
    24.             stream.Close();
    25.  
    26.             return data;
    27.         }
    28.         else
    29.         {
    30.             Debug.LogError("Save file not found in " + path);
    31.             return null;
    32.         }
    33.     }
    34.  
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,726
    I have not reviewed this tutorial so it might be best to ask the creator of the video directly.

    Judging solely from the code above, it appears he is placing all the code he wants saved into a single class (which he calls a Player01Data) and then the load/save code above just streams the contents of that class to or from the save file.

    If you wanted to have more things saved, you would get them into the Player01Data structure, and then they would be automatically included into the stream. NOTE: this code would not automatically handle the data changing between the time you SAVE it and then LOAD it, so you would want to handle your own save versioning.
     
  3. alexxjaz

    alexxjaz

    Joined:
    Sep 18, 2018
    Posts:
    45
    And do you know if I can save here lists of GameObjects for example? I know that it doesnt support Vector 3 for example, so I highly doubt that supports GO.
    And what do you mean by that doesnt handle the data?
     
  4. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,726
    It doesn't handle YOU changing the shape of a save game, i.e., adding or removing a class member. No idea what it would do.

    I have no idea what any of this does; you have it running, you should experiment!
     
  5. calpolican

    calpolican

    Joined:
    Feb 2, 2015
    Posts:
    425
    Usually you can't save Vectors. GameObjects either. Actually you can't save monobehaviours in general.
    For this kind of things what you should do is create a special class.
    For example, to save a vector3, you can create a class like this and put it in your script folder.

    Code (CSharp):
    1. [System.Serializable]
    2. public class SerializableVector3
    3. {
    4.     public float x;
    5.     public float y;
    6.     public float z;
    7.  
    8.     //whenever you want to create a serializable vector out of a Vector you do "new SerializableVector3 (yourVector);"
    9.     public SerializableVector3 (Vector3 yourVector){
    10.         x = yourVector.x;
    11.         y = yourVector.y;
    12.         z = yourVector.z;
    13. }
    14. }
    15.  
    then, suppouse you want for example to save the position of your character, you just do:
    Code (CSharp):
    1. SerializableVector3 = new SerializableVector3 (myCharacter.transform.position);
    for game objects, just make a serializable class that only stores the thiings you want to save, like the position and health of the character, or whatever.
     
    Last edited: Jun 27, 2019
  6. dgoyette

    dgoyette

    Joined:
    Jul 1, 2016
    Posts:
    4,195
    The "big picture" when it comes to saving data is that you can't simply save anything. You can only save data that is serializable. A GameObject, for example, is not strictly serializable. It will have all sorts of references to other things which aren't easily represented as simple data in a file. So any time you want to implement the ability to save the state of the game to a file, what you're talking about is extracting all of the essential information from the scene, such that you could reassign all those values later and return the game to the state it was at when you saved.

    Some things are pretty easy. The video shows him setting up a special class for holding the data. He has a couple of ints, and an array of floats for holding the components of a Vector3. That's might be enough for a simple game, and the basic approach is completely valid. The difficulty ramps up the greater the number and complexity of things you need to save. If you just need to save a few stats and some positions, it's pretty simple. But if your game uses realistic physics, now you probably want to save every rigidbody's velocity and angular velocity as well. If you game supports objects dynamically spawning (like enemies), you probably need to save all of their data, like what kind of enemy it was (so you can reinstantiate the proper kind of enemy when reloading), along with potentially complex stuff related to its AI, such as whether it was pursuing the player when you saved, whether it was patrolling some area, whether it was preparing a complex attack, etc. You can image this kind of thing can get really complicated.

    Ultimately, a robust save/load system comes down to whether you engineer your game to expose the state of each object, and whether you engineer it to set a component's state from raw data. That's the kind of thing you need to plan for, and it can be a lot of work.

    Lots of games have a Quick Save option, allowing you to reload exactly as it was when you saved. These games save the smallest details, sometimes as specific as making sure that some dialog a person was saying resumes at the correct moment, or that some animation a character is performing resumes from the right point. Getting that to all work is a lot of work.

    Anyway, this is getting rambling, but the message is: Consider how much you really need to save, because the more stuff the more difficult it gets.
     
  7. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,726
    @dgoyette That was an awesome summary. Bravo.
     
  8. alexxjaz

    alexxjaz

    Joined:
    Sep 18, 2018
    Posts:
    45
    Thx for the explanation, it was very helpfull , I will keep the things simple since Im newby in saving data.
     
  9. wimpire

    wimpire

    Joined:
    Aug 16, 2020
    Posts:
    2
    i think saving and loading is too hard, thats why i just stop making games when it comes to that section
     
    berber_hunter and mitaywalle like this.