ScriptableObject и MonoBehaviour
ScriptableObject и MonoBehaviour
На первый взгляд объекты ScriptableObject устроены просто: их API содержит всего несколько методов. В данном случае это преимущество, поскольку чем проще система, тем меньше вероятность ошибок.
UML-диаграмма объектов Unity
Как и MonoBehaviour, класс ScriptableObject наследуется от UnityEngine.Object.
Сравнение Лучше всего понять ScriptableObject в сравнении с родственным ему классом MonoBehaviour. В таблице показаны их сходства и различия. MonoBehaviour
ScriptableObject
И MonoBehaviour, и ScriptableObject являются типами. скриптов. Классы MonoBehaviour и ScriptableObject наследуются от UnityEngine.Object.
Компоненты MonoBehaviour получают обратные вызовы от Unity. Чтобы связать методы с циклом PlayerLoop игрового движка, назовите их в соответствии с функциями событий MonoBehaviour, например Update(). Например: Start, Awake, Update, OnEnable, OnDisable, OnCollisionEnter
Объекты ScriptableObject не получают большинство обратных вызовов жизненного цикла Unity, таких как Update, Start и FixedUpdate. Во время выполнения объекты ScriptableObject поддерживают ограниченный набор функций событий: Awake, OnEnable, OnDestroy и OnDisable. Редактор Unity также вызывает OnValidate и Reset при работе с окном Inspector. В ScriptableObject можно определять и другие методы, но PlayerLoop не вызывает их автоматически.
Во время выполнения компоненты MonoBehaviour должны быть прикреплены к объектам GameObject.
Объекты ScriptableObject не привязаны к конкретному GameObject.
Для создания MonoBehaviour во время выполнения используйте API AddComponent.
Сохраняйте объекты ScriptableObject в отдельных файлах ассетов на уровне проекта, а затем обращайтесь к ассету ScriptableObject из компонента MonoBehaviour или другого скрипта.
Данные MonoBehaviour сохраняются внутри сцен и префабов.
Каждый экземпляр ScriptableObject можно сохранить в отдельном файле ассета на уровне проекта.
В редакторе Unity изменения значений MonoBehaviour сбрасываются после выхода из режима Play.
В редакторе Unity изменения значений ScriptableObject не сбрасываются после выхода из режима Play. В автономной сборке изменения значений ScriptableObject во время выполнения не сохраняются.
MonoBehaviour и ScriptableObject поддерживают сериализацию и отображаются в окне Inspector.
Обратные вызовы и сообщения Объекты ScriptableObject поддерживают лишь часть функций событий, доступных MonoBehaviour. В них можно создавать собственные методы, но вызывать эти методы необходимо самостоятельно. В таблице ниже приведены только методы, которые PlayerLoop вызывает автоматически.
Функция события
Когда вызывается
(во время выполнения)
Awake
Вызывается при запуске скрипта ScriptableObject, аналогично обратному вызову Awake у MonoBehaviour. Awake также выполняется при запуске игры или загрузке сцены, содержащей ссылку на ассет ScriptableObject.
OnEnable
Вызывается сразу после Awake при загрузке или создании экземпляра ScriptableObject. OnEnable выполняется при вызове ScriptableObject.CreateInstance или после успешной повторной компиляции скриптов.
OnDisable
Вызывается, когда ScriptableObject выходит из области использования: например, при загрузке сцены без ссылок на его ассет или непосредственно перед OnDestroy этого ScriptableObject.
Unity также выполняет OnDisable перед повторной компиляцией скриптов. При входе в режим Play метод OnDisable вызывается непосредственно перед OnEnable.
OnDestroy
Вызывается при уничтожении ScriptableObject, например при его удалении в редакторе Unity или из кода. Если ScriptableObject создан во время выполнения, OnDestroy также вызывается при завершении приложения или выходе редактора Unity из режима Play. Примечание: уничтожается только нативная C++-часть объекта. Подробнее см. раздел «Создание и жизненный цикл».
Функции только для редактора Unity
Когда вызывается
OnValidate
Выполняется при загрузке скрипта или изменении значения в окне Inspector. Метод можно использовать, чтобы удерживать данные в допустимом диапазоне.
Reset
Вызывается при выборе команды Reset в контекстном меню окна Inspector.
Чтобы уничтожить ScriptableObject, удалите его в редакторе Unity либо вызовите Destroy или DestroyImmediate во время выполнения. Ниже кратко показаны функции событий и жизненный цикл ScriptableObject. Сравните их с порядком выполнения функций событий MonoBehaviour, двигаясь сверху вниз.
Инициализация
Редактор Unity
Завершение работы
Функции событий ScriptableObject и порядок их выполнения
Файлы Одно из главных различий между MonoBehaviour и ScriptableObject заключается в способе сохранения данных. Unity сериализует компоненты MonoBehaviour внутри файлов сцен или префабов. Сохраняются следующие данные: - Сам MonoBehaviour - Связанный с ним GameObject - Его Transform - Остальные компоненты и MonoBehaviour на том же GameObject
MonoBehaviour прикрепляется к GameObject
ScriptableObject находится в проекте ScriptableObject и MonoBehaviour
В отличие от MonoBehaviour, Unity сохраняет объекты ScriptableObject в отдельных файлах ассетов. Такие файлы меньше, а данные в них лучше обособлены, чем в случае с MonoBehaviour.
Если в окне Project Settings > Asset Serialization выбрать Mode: Force Text, ассет ScriptableObject можно открыть в текстовом редакторе. Он будет выглядеть примерно так:
Экземпляр ScriptableObject, сериализованный в текстовом виде
YAML - не язык разметки Unity использует высокопроизводительную библиотеку сериализации, реализующую подмножество спецификации YAML. Это легковесный и удобочитаемый язык, родственный XML и JSON. В YAML данные организованы в иерархию вложенных элементов. У каждого объекта есть Class ID, File ID и тип объекта. Обратите внимание: для ScriptableObject используется тип «MonoBehaviour», а не отдельный собственный тип.
ID класса
ID файла
Тип объекта
Пары ключ-значение
Заголовок объекта в YAML
Под каждым объектом перечислены его сериализованные свойства в виде пар «ключ значение». Подробнее см. статью «Разбираемся в языке сериализации YAML в Unity».
Создание и жизненный цикл Жизненный цикл ScriptableObject похож на жизненный цикл любого другого ассета проекта, например материала или текстуры. Как и в предыдущем примере, добавьте к скрипту атрибут [CreateAssetMenu], чтобы создать пользовательскую команду меню в редакторе Unity. При необходимости можно задать имя файла по умолчанию через fileName и порядок пункта меню через order. Ниже показан наиболее распространенный способ создания ассета ScriptableObject.
[CreateAssetMenu(fileName="MyScriptableObject"] public class MyScriptableObject: ScriptableObject { public int SomeVar; }
Чтобы создать экземпляр ScriptableObject во время выполнения, вызовите статический метод CreateInstance: ScriptableObject.CreateInstance<MyScriptableObjectClass>();Уничтожение ScriptableObject Как и другие объекты Unity, ScriptableObject состоит из нативной C++-части и управляемой C#-части. Нативную часть можно уничтожить напрямую, но управляемая останется до очистки сборщиком мусора (GC). Такая очистка выполняется при смене сцены или вызове Resources.UnloadUnusedAssets.
Нативная сторона
Экземпляр C++ ScriptableObject
Управляемая сторона
Экземпляр C# ScriptableObject
Ссылка на ScriptableObject
У ScriptableObject есть нативная и управляемая части.
Чтобы не задерживать сборку мусора, явно присвойте null всем ссылкам на ассет ScriptableObject. Примечание: ссылки важно обнулить до вызова Destroy или DestroyImmediate. Иначе ссылка в редакторе Unity может отображаться как null, хотя управляемый объект все еще существует. GC очистит его только после удаления всех ссылок на ScriptableObject.
Освоив создание и уничтожение собственных ScriptableObject, можно перейти к более творческим способам их применения в игре.