Всем привет!
Наверное каждый, кто начал делать игры на Unity столкнулся с дилеммой как сохранить игровой прогресс. Сегодня я вам расскажу про мой способ. Он не новый, но вполне себе рабочий.
Если интересно, добро пожаловать под кат.
Когда я задумался над тем как мне сохранять данные, то пришел к выводу что мне будет удобно сериализировать данные в JSON. Чтобы не городить очередной велосипед я принял решение использовать популярную библиотеку Json.NET — Newtonsoft. Тем более она может сохранять объекты и их типы.
На данный момент класс доступа к данным статический, это значит что доступ к нему можно получить из любого места. Минусы — нельзя сделать раздельные сохранения.
Немного разберем код:
Так как нельзя написать:
Мы обернем SaveItem в ISaveItem. Тем самым мы сможем создать словарь с разными типами данных.
Если вы попробуете сериализовать Vector2 или Vector3 или Color или другие типы данных движка Unity, то скорее всего получите ошибку зацикливания. Чтобы избежать данную проблему в Json.NET — Newtonsoft есть для этого решение: создание конвертеров. Давайте разберем один из них.
Создаем класс и наследуемся от JsonConverter:
Создаем конструктор и приватное поле:
После переопределям методы:
Самое главное в методе WriteJson. Тут происходит сохранение данных.
А теперь как пользоваться моей системой сохранений:
Чтобы сохранить данные пишем:
Чтобы прочитать данные пишем:
В теории можно запросто сохраняться сложные структуры данных и это должно работать. Давайте попробуем сохранить и прочитать объект посложнее:
Как видим, все прекрасно работает.
Так же можно отредактировать сохранения, импортировать, экспортировать или удалить.
![](https://habrastorage.org/webt/vi/ae/pf/viaepfdn9ycmrdmmjz_ntdltz08.png)
Редактор может показывать как обычные типы (int, float, string и т.д.). Так и более сложные.
![](https://habrastorage.org/webt/5f/tq/lb/5ftqlbmmybry1twio6q-qhdfar0.png)
![](https://habrastorage.org/webt/az/z8/sp/azz8spw9nihj07wv8meiw8e0r-e.png)
Даже массивы:
![](https://habrastorage.org/webt/x_/p-/o5/x_p-o5kchpdci-vyw8gu3d1xiwo.png)
Спасибо за внимание. Ссылка на проект в GitHub.
Наверное каждый, кто начал делать игры на Unity столкнулся с дилеммой как сохранить игровой прогресс. Сегодня я вам расскажу про мой способ. Он не новый, но вполне себе рабочий.
Если интересно, добро пожаловать под кат.
Когда я задумался над тем как мне сохранять данные, то пришел к выводу что мне будет удобно сериализировать данные в JSON. Чтобы не городить очередной велосипед я принял решение использовать популярную библиотеку Json.NET — Newtonsoft. Тем более она может сохранять объекты и их типы.
На данный момент класс доступа к данным статический, это значит что доступ к нему можно получить из любого места. Минусы — нельзя сделать раздельные сохранения.
Немного разберем код:
public abstract class ISaveItem
{
public string Key { get; set; }
}
Так как нельзя написать:
Dictionary<string, SaveItem<T>>
Мы обернем SaveItem в ISaveItem. Тем самым мы сможем создать словарь с разными типами данных.
public class SaveItem<T> : ISaveItem
{
public T item;
}
private static Dictionary<string, ISaveItem> items;
Если вы попробуете сериализовать Vector2 или Vector3 или Color или другие типы данных движка Unity, то скорее всего получите ошибку зацикливания. Чтобы избежать данную проблему в Json.NET — Newtonsoft есть для этого решение: создание конвертеров. Давайте разберем один из них.
Создаем класс и наследуемся от JsonConverter:
public class Vector2Converter : JsonConverter
Создаем конструктор и приватное поле:
private readonly Type type;
public Vector2Converter(Type type)
{
this.type = type;
}
После переопределям методы:
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();
}
}
Самое главное в методе WriteJson. Тут происходит сохранение данных.
А теперь как пользоваться моей системой сохранений:
Чтобы сохранить данные пишем:
int myInt = 33;
SaveSystem.Set("MyInt", myInt);
Чтобы прочитать данные пишем:
var myInt = SaveSystem.Get<int>("MyInt");
В теории можно запросто сохраняться сложные структуры данных и это должно работать. Давайте попробуем сохранить и прочитать объект посложнее:
[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);
Как видим, все прекрасно работает.
Так же можно отредактировать сохранения, импортировать, экспортировать или удалить.
![](https://habrastorage.org/webt/vi/ae/pf/viaepfdn9ycmrdmmjz_ntdltz08.png)
Редактор может показывать как обычные типы (int, float, string и т.д.). Так и более сложные.
![](https://habrastorage.org/webt/5f/tq/lb/5ftqlbmmybry1twio6q-qhdfar0.png)
![](https://habrastorage.org/webt/az/z8/sp/azz8spw9nihj07wv8meiw8e0r-e.png)
Даже массивы:
![](https://habrastorage.org/webt/x_/p-/o5/x_p-o5kchpdci-vyw8gu3d1xiwo.png)
Спасибо за внимание. Ссылка на проект в GitHub.
sith
Заём сохранять в JSON? Кто-то будет читать глазами сохранённый файл? Если не будет, то почему бы не сохранить в бинарном формате, при этом по пути сжав данные и, при желании, зашифровав? Кроме того, сохранять состоянии игры, в общем случае, принято на сервер (где сжатие и шифрование данных ещё более актуально), а не на диск
Kilosoft Автор
Конечно же в 99% случаев никто не будет глазами читать/править файл. Но в целом такая возможность есть. Так же можно переписать на бинарный вариант, это не проблема на самом деле.