Сохранение прогресса - Stone of Adventure

Всем привет! Сегодня будет немного технической информации про наш проект, думаю это будет особенно интересно тем, кто планирует или уже работает в GameDev.

Как вы возможно уже знаете сейчас мы активно работаем над глобальной картой и мета механиками. Одной из важных частей любой игры длиною больше 15 минут является система сохранения прогресса игрока. Прогресс в Stone of Adventure можно разделить на два типа: глобальный прогресс и прогресс в рамках сессии. В рамках глобального прогресса мы будем сохранять разблокированные карты и предметы, а также прогресс квестов. В рамках сессии будем сохранять состояние текущей колоды и инвентаря, а также глобальной карты и многое другое.

Процесс сохранения данных о забеге выглядит как-то так
Процесс сохранения данных о забеге выглядит как-то так

Для сохранения всех этих данных мы используем сериализацию в json. Это процесс, при котором данные игры конвертируются в текстовый файл, который можно записать на диск. К сожалению не любые данные в Unity можно перевести в текстовый формат.


У нас в игре используется много конфигов для настройки карт, юнитов и генерации карт. В рамках движка это называется ScriptableObject и хранится в виде ассетов в проекте, подобно тому как хранятся текстуры, 3d модели и звуки. При сериализации таких объектов сохраняется их InstanceID. Это идентификатор, который движок генерирует для объектов при запуске игры. Это значит, что при попытке загрузить сейв скорее всего ничего не получится, потому что InstanceID нужного ассета изменился.

При сохранении ScriptableObject сериализуется динамический InstanceID
При сохранении ScriptableObject сериализуется динамический InstanceID

Мы не можем напрямую сериализовать ассеты в Unity. Поэтому мы решили немного изменить подход и сохранять GUID ассета. Это тоже идентификатор, но постоянный. Он генерируется при создании или добавлении ассета в проект и не меняется. Удобство заключается в том, что мы можем загружать объекты по их GUID с помощью Addressables. Это расширение для Unity позволяющее более гибко контролировать, что именно загружено в оперативную память.

Пример загрузки с помощью Addressables через GUID
Пример загрузки с помощью Addressables через GUID

Последнее препятствие на пути к решению задачи остаётся то, что в Unity нет способа получить GUID объекта в процессе игры. Его можно определить только в редакторе. Поэтому было решено написать небольшой скрипт, который наследует от ScriptableObject и при создании ассета сохраняет его GUID. Это позволяет в процессе игры сохранить GUID ассета и при следующем запуске загрузить его из Addressables.

Обертка над ScriptableObject для сохранения GUID при создании ассета
Обертка над ScriptableObject для сохранения GUID при создании ассета

Спасибо, что дочитали до конца! Надеюсь статья была для вас полезна. Подписывайтесь на сообщество, оставляйте комментарии и делитесь своим мнением. Также добавляйте игру в желаемое ->

7
1
3 комментария