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

Saving a scene

Discussion in 'Scripting' started by Morseton, Jan 30, 2016.

  1. Morseton

    Morseton

    Joined:
    Jan 15, 2016
    Posts:
    90
    Is it possible to save a whole scene in a file and then load it again? As a save/load system?

    if it's not possible, what's the best way and easiest to make a save and load system for a game?
     
  2. Teravisor

    Teravisor

    Joined:
    Dec 29, 2014
    Posts:
    654
    You can serialize all objects that you have and deserialize them - that's how Unity expects us to Save/Load. Search for "Unity Serialization" and such. Scenes are big "prefabs" with resources needed to load them; you can't save them runtime.
     
  3. Morseton

    Morseton

    Joined:
    Jan 15, 2016
    Posts:
    90
    I watched a youtube video explaining how to save, i tested and it works. but it only shows how to save a float,int etc

    now my question is: How to save a game object?

    And if I save a game object, which stats will go with that save? Transform(positions, rotations, etc), physics,scripts + script variables with each saved variable?

    or do I need to save each of these individually?

    for loading this gameobject, do I need to instantiate it?
     
  4. Teravisor

    Teravisor

    Joined:
    Dec 29, 2014
    Posts:
    654
    Oh, right. You must've looked at just serialization without saving/loading.This tutorial explains saving/loading some data into file. You will still need to manually pass each and every object you want saved to it by calling bf.Serialize(file, object); and calling bf.Deserialize(file) with typecast of what you've written there.
     
    Last edited: Jan 30, 2016
  5. Morseton

    Morseton

    Joined:
    Jan 15, 2016
    Posts:
    90
    yes, I'm doing that!

    here's my Save script

    Code (CSharp):
    1. BinaryFormatter binary = new BinaryFormatter ();
    2.         FileStream fStream = File.Create (filePath);// parecido ao ini_open
    3.  
    4.         // new reference
    5.         SaveManager saver = new SaveManager();
    6.         saver.minerals = GameObject.FindGameObjectWithTag ("Solar Station").GetComponent<solarStationController>().Minerals;
    7.         saver.energy = GameObject.FindGameObjectWithTag ("Solar Station").GetComponent<solarStationController>().Energy;
    8.  
    9.         binary.Serialize (fStream,saver);
    10.         fStream.Close ();
    but my problem now is saving gameobjects, and not variables
     
  6. Deleted User

    Deleted User

    Guest

    You can't save out GameObjects in this way, you can, however, add any non-MonoBehaviour class marked as [System.Serializable] as an object and reload it.

    I wrote this real quick and didn't test it but I've written full serialization for 3 games and this is basically what I do. I store data in classes so it gives me full control over what should be serialized reducing unnecessary serialization which is great for performance.

    Code (CSharp):
    1. public class SaverObjects
    2.     {
    3.         public static List<object> savedData = new List<object>();
    4.  
    5.         public static void Save()
    6.         {
    7.             SaveManager saver = new SaveManager("Solar Station");
    8.  
    9.             BinaryFormatter bf = new BinaryFormatter();
    10.             MemoryStream memoryStream = new MemoryStream();
    11.             bf.Serialize(memoryStream, saver.savedObjects);
    12.             string tmp = System.Convert.ToBase64String(memoryStream.ToArray());
    13.             PlayerPrefs.SetString("savedData", tmp);
    14.         }
    15.  
    16.         public static void Load()
    17.         {
    18.             BinaryFormatter bf = new BinaryFormatter();
    19.             string tmp = string.Empty;
    20.             string prefsString = PlayerPrefs.GetString("savedData", tmp);
    21.             MemoryStream memoryStream = new MemoryStream(System.Convert.FromBase64String(prefsString));
    22.             List<object> objectList = (List<object>)bf.Deserialize(memoryStream);
    23.             SaveManager loader = new SaveManager("Solar Station");
    24.             loader.Reload(objectList);
    25.         }
    26.     }
    27.  
    28.     [System.Serializable]
    29.     public class SaveManager
    30.     {
    31.         public SolarStationController solarStationController;
    32.         public List<object> savedObjects = new List<object>();
    33.         public SaveManager(string tagName)
    34.         {
    35.             solarStationController = GameObject.FindGameObjectWithTag(tagName).GetComponent<SolarStationController>();
    36.             savedObjects.Add(solarStationController.SaveData);
    37.         }
    38.  
    39.         public void Reload(List<object> objData)
    40.         {
    41.             savedObjects = objData;
    42.             solarStationController.LoadData = objData[0];
    43.         }
    44.     }
    45.  
    46.     public class SolarStationController : MonoBehaviour
    47.     {
    48.         private SolarControllerSaveData data = new SolarControllerSaveData();
    49.  
    50.         public void DepleteEnergy(float amt)
    51.         {
    52.             data.energy -= amt;
    53.         }
    54.  
    55.         public object SaveData
    56.         {
    57.             get
    58.             {
    59.                 return data;
    60.             }
    61.         }
    62.  
    63.         public object LoadData
    64.         {
    65.             set { data = (SolarControllerSaveData)value; }
    66.         }
    67.  
    68.         [System.Serializable]
    69.         private class SolarControllerSaveData
    70.         {
    71.             public float minerals = 50;
    72.             public float energy = 25;
    73.         }
    74.     }

    I fixed it up and ran a test it should work now. I just wanted to demonstrate really how you can encapsulate data in classes (or structs but that's another topic) and save those classes out as objects. It gives you a much finer control over what exactly you want to be saving and loading in your game. By saving and loading only what's necessary, you save hard disk space for the player and you increase performance.
     
    Last edited by a moderator: Jan 30, 2016
  7. Morseton

    Morseton

    Joined:
    Jan 15, 2016
    Posts:
    90
    That sounds kinda complex for me to understand haha

    1 question:
    I come from Game Maker, and to save objects there, for example if I wanted to save All the asteroids in my map, I would first save a variable that would store the total number of asteroids. Then I would save the x,y position and other variables needed.

    then for loading, do a for() loop, from 1 to asteroidsNumber, and create an asteroid instance and load its variables(x,y,etc).

    I think this can work for Unity too, what do you say? it sounds easier for me than saving directly gameobjects
     
  8. Teravisor

    Teravisor

    Joined:
    Dec 29, 2014
    Posts:
    654
    It will work if you save all its variables(and load too). If you forget some... Depends.
     
  9. Morseton

    Morseton

    Joined:
    Jan 15, 2016
    Posts:
    90
    mhmm which variables are you refering to?
     
  10. Teravisor

    Teravisor

    Joined:
    Dec 29, 2014
    Posts:
    654
    Transform's position, rotation, scale; if objects have other components... Any variables they have?
     
  11. Morseton

    Morseton

    Joined:
    Jan 15, 2016
    Posts:
    90
    On my game, rotations aren't needed! I guess I'll try to do it! Thank you for the answers