Unity API has a class called ‘PlayerPrefs’ which allows saving basic data types with a string key. But when a game becomes complex ‘PlayerPrefs’
can't save all the data and it's so hard to access them as you have to remember
all the keys and call one by one. To avoid this we can create a custom save
system which can save a class at once which contains all the data values.
We need two scripts for this save-system.
01.SaveSystem
class
02.SaveData
class
Save system class will contain all the methods to save and
retrieve data and ‘SaveData’ class is used as the base class for the classes we
going to create to store data.
‘SaveData’ class doesn’t contain any methods and not
extended by any other classes or interfaces. Make sure to mark this class as
‘[System.Serializable]’ in order to make sure this is serializable.
[System.Serializable] public class SaveData { }
‘SaveSystem’ class contains 3 methods. One for
initialization and you can add this to the Awake method. Class is in singleton
pattern to make sure this class won't get destroyed when switching scenes. This
class saves all the data as binary files and this class doesn’t support unity
API data structures and generic data structures.
public class SaveSytem : MonoBehaviour { private static SaveSytem instance; private List<String> pathList = new List<string>(); private string extensionType = "technoob"; private void Awake() { #region SINGLETON if (instance == null) instance = this; else if(instance!= this) Destroy(gameObject); DontDestroyOnLoad(gameObject); #endregion InitSaveSystem(); } /// <summary> /// Saves the class passed to this method /// </summary> /// <param name="saveData">Class which is extended by SaveData class</param> /// <param name="_datapacketId">This should be unique for each class you save</param> public static void SaveGame(SaveData saveData , string _datapacketId) { BinaryFormatter binaryFormatter = new BinaryFormatter(); string path = Application.persistentDataPath; if (!instance.pathList.Contains(_datapacketId)) instance.pathList.Add(_datapacketId); path = Application.persistentDataPath + "/" + _datapacketId + instance.extensionType; FileStream stream; if (File.Exists(path)) stream= new FileStream(path, FileMode.Open); else stream = new FileStream(path, FileMode.CreateNew); binaryFormatter.Serialize(stream , saveData); stream.Close(); int x = instance.pathList.Count; String[] paths = new string[x]; for (int i = 0; i < x; i++) { paths[i] = instance.pathList[i]; } path = Application.persistentDataPath + "/settings.technoob"; if (File.Exists(path)) stream= new FileStream(path, FileMode.Open); else stream = new FileStream(path, FileMode.CreateNew); binaryFormatter.Serialize(stream , paths); stream.Close(); } /// <summary> /// Returns saved class for the unique string id /// </summary> /// <param name="_dataPacketId">Unique string id for the saved class</param> /// <returns></returns> public static SaveData GetSaveData(string _dataPacketId) { BinaryFormatter binaryFormatter = new BinaryFormatter(); string path = Application.persistentDataPath + "/" + _dataPacketId + instance.extensionType; if (File.Exists(path)) { FileStream stream = new FileStream(path, FileMode.Open); SaveData _data = binaryFormatter.Deserialize(stream) as SaveData; stream.Close(); return _data; } else { Debug.LogError("Data packet " + _dataPacketId + " not found! - SaveSystem"); return null; } } #region INITIALIZATION public static void InitSaveSystem() { BinaryFormatter binaryFormatter = new BinaryFormatter(); string path = Application.persistentDataPath + "/settings.technoob" ; if (File.Exists(path)) { FileStream stream = new FileStream(path, FileMode.Open); String[] paths = binaryFormatter.Deserialize(stream) as string[]; for (int i = 0; i < paths.Length; i++) { instance.pathList.Add(paths[i]); } stream.Close(); } Debug.Log("Init Save System"); } #endregion }
The class which contains the data you wanna save should be
extended from the SaveData class. Make sure to mark that class as
[System.Serializable]. After that, you
can call the SaveGame method by passing that class and a string key to access
that class later. You can simply call the GetSaveData method by passing the
string key when you want to retrieve the data again. You don’t need to worry
about the extension of the save files as this class saves the data as binary
files.
You can create a custom converter class to convert none serializable data types into serializable data types like converting color to a float array.
All these scripts with a demo scene are available on GitHub.
Related Articles
You can create a custom converter class to convert none serializable data types into serializable data types like converting color to a float array.
All these scripts with a demo scene are available on GitHub.
Related Articles
Comments
Post a Comment