Data storage / loading system

Hello!



Probably everyone who started making games on Unity was faced with the dilemma of how to save game progress. Today I will tell you about my method. He is not new, but quite a working man.



If interested, welcome to cat.



When I thought about how to save data, I came to the conclusion that it would be convenient for me to serialize data in JSON. In order not to make another bicycle, I decided to use the popular Json.NET library - Newtonsoft. Moreover, it can save objects and their types.



At the moment, the data access class is static, which means that you can access it from anywhere. Cons - you cannot make separate save.



Let's analyze the code a bit:



public abstract class ISaveItem { public string Key { get; set; } }
      
      





Since it is impossible to write:



 Dictionary<string, SaveItem<T>>
      
      





We will wrap SaveItem in ISaveItem. This way we can create a dictionary with different types of data.



 public class SaveItem<T> : ISaveItem { public T item; } private static Dictionary<string, ISaveItem> items;
      
      





If you try to serialize Vector2 or Vector3 or Color or other data types of the Unity engine, you will most likely get a looping error. To avoid this problem in Json.NET - Newtonsoft there is a solution for this: the creation of converters. Let's analyze one of them.



Create a class and inherit from JsonConverter:



 public class Vector2Converter : JsonConverter
      
      





Create a constructor and private field:



 private readonly Type type; public Vector2Converter(Type type) { this.type = type; }
      
      





After redefining the methods:



 public override bool CanConvert(Type objectType) { return type == objectType; } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { return null; } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { if (value.GetType() == type) { var vector = (Vector2)value; writer.WriteStartObject(); writer.WritePropertyName("X"); writer.WriteValue(vector.x); writer.WritePropertyName("Y"); writer.WriteValue(vector.y); writer.WriteEndObject(); } }
      
      





The most important thing in the WriteJson method. This is where data is saved.



And now how to use my save system:



To save the data we write:



 int myInt = 33; SaveSystem.Set("MyInt", myInt);
      
      





To read the data we write:



 var myInt = SaveSystem.Get<int>("MyInt");
      
      





In theory, complex data structures can easily be stored and this should work. Let's try to save and read the object more complicated:



 [System.Serializable] public class Test { public string Name; public float FloatParam; } Test test = new Test() {Name = "TestValue1", FloatParam = 0.1f}; // SaveSystem.Set("MyTestClass", test); // var saveTest = SaveSystem.Get<Test>("MyTestClass"); Debug.Log(saveTest.Name); Debug.Log(saveTest.FloatParam);
      
      





As you can see, everything works great.



You can also edit the save, import, export or delete.







The editor can show as ordinary types (int, float, string, etc.). So are more complex.











Even arrays:







Thanks for your attention. Link to the project on GitHub .



All Articles