Как использовать ScriptableObject и упростить себе жизнь
Любой движок предоставляет пользователю набор инструментов для работы. Движок во многом упрощает жизнь разработчикам, однако лишь в том случае, если разработчик правильно использует эти инструменты.
В Unity существует самый известный базовый класс — MonoBehaviour и большая часть скриптов наследует от него.Этот класс содержит все методы, необходимые для работы в Unity. Например Start(), Update(), Instantiate(), GetComponent() и множество других.
MonoBehaviour- скрипты обязаны прикрепляться к объектам. Они существуют в префабах и сцене. Содержат функции, которые реагируют на события Unity: Awake(), Update(), OnTriggerEnter() и другие. Применение этих скриптов вполне понятно: “объект, сделай что-нибудь, когда получишь сигнал”.
Существует также класс ScriptableObject, применение которого не так очевидно и требует пояснений.
У ScriptableObject есть свои особенности:
- Они не находятся в сцене — не изменяются при переключении режима игры.
- Имеют мало callback-ов — OnEnable(), OnDisable(), OnDestroy().
- Хранятся как .asset файлы.
Подобные характеристики открывают очень много возможностей, как например, хранение данных, быстрое изменение параметров объектов, простота в совместной работе.
Самое важное отличие ScriptableObject от MonoBehaviour это то, как они проходят сериализацию.
Что такое сериализация
Если коротко, то сериализация — это способ записи данных для хранения: на диск или в файл. Процесс сериализации — это кодировка данных в последовательность байтов для последующего сохранения или передачи в память, на диск или просто файл. Данные, сохраненные таким образом позже можно воссоздать, например в процессе выполнения программы. Такой процесс имеет название — десериализация. Сам объект сериализуется в поток, который, помимо данных, содержит еще и информацию о самом объекте — версия, тип объекта, язык, имя сборки и тд.
Существует тонна способов проводить сериализацию объектов
В Unity есть свой способ сериализации объектов и данных. Например сохранение файлов в текст, json и тд.
Сериализация в Unity
Когда мы запускаем или отключаем режим игры (play-mode) или изменяем какой-нибудь скрипт в Unity, все сборки с .dll-ками проекта должны быть перезагружены. Тут и происходит процесс сериализации\десериализации.
Это значит, что все изменения сделанные в режиме игры не будут сохранены при выходе из него. И во время работы в Unity это важно помнить — наверняка многие совершали такую ошибку: отредактировать сцену, выставить все на свои места,а потом выйти из play mode и все потерять.
Поля в классах, наследуемых от MonoBehaviour, сериализуются просто как значения. Поэтому, при десериализации может произойти следующее: ссылка на объект пропадает, но создается копия этого объекта. Подобное приводит к потере связей между объектами.
ScriptableObjects во время сериализации
Ссылки на ScriptableObjects сохраняются как ссылки (references) а значит взаимодействия между объектами сохраняются при сериализации\десериализации и данные не повторяются.
Очень важно знать что SO не находятся в сцене и поэтому они не проходят процесс сериализации\десериализации во время запуска play-mode или перезагрузки сборок. И это самое важное, так как изменения, сделанные в SO во время работы play-mode будут сохраняться при выходе из него! Что значительно упрощает жизнь во время разработки и открывает новые возможности.
Используем ScriptableObject для хранения данных
Например, в игре есть разные враги. Но у всех врагов есть статистика в виде их очков здоровья, показателей атаки или скорости передвижения.
Конечно, можно создать пустой префаб в котором хранить эти данные, но это не то, для чего существуют префабы.Мало того, подобное легко приводит к ошибкам, которые тяжело исправлять.
Достичь нужного результата можно с помощью ScriptableObject. Создается SO в котором есть нужные поля. Что бы создавать объекты SO через инспектор обозначаем класс как [CreateAssetMenu] и у в Asset-Create появляется пункт с названием нашего SO.
Код выглядит примерно так:
Теперь этот SO можно создать как обычный объект — материал или спрайт через Create — [Имя класса].
Это теперь — шаблон по которому будут создаваться все враги в игре. А для каждого экземпляра можно настраивать свои параметры.
Что бы присвоить игровому объекту созданные значения нужно создать ссылку на SO в MonoBehaviour-скрипте. И всё — мы получили отличную систему хранения данных, которая не удаляется при перезапусках игры, значения не сбрасываются, а сам файлик хранится как .asset — один файл-один объект и к тому же легко управляем.
Тем, кто хочет перейти от создания прототипов и маленьких проектов к чему-то более серьезному и масштабному следует обратить внимание на SciptableObjects — они могут значительно упростить жизнь и в разы ускорить разработку игры.
Всем остальным так же будет полезно обратить на них внимание — никогда не рано упростить себе жизнь. А если хотите изучать работу в Unity или продвинуться в освоении движка, существует хороший сайт https://unity3dschool.ru, где вы найдете уроки по разным темам. На сайте можно найти и то, что полезно новичкам, и то что интересно для более продвинутых пользователей. Заходите — знакомьтесь.