Post image

Ассеты ScriptableObject и ScriptableWizard для создания

Часто, при разработке игры необходимо сохранить объект с данными который должен быть доступен из редактора. Например конфигурацию, данные для уровня или другие заготовки. Для этого в Unity предусмотрен ScriptableObject - спец. класс позволяющий создавать ресурсы без прикрепления скрипта к GameObject игровому объекту.

ScriptableObject

Для того чтобы создать ресурс содержащий данные необходимо написать класс наследующий ScriptableObject, с полями для необходимых данных. Пусть он называется DataHolder

Использование многомерного массива (например int[,]) в наследнике ScriptableObject, при запуске play mode, вызывает внутреннюю ошибку NullReferenceException: (null) UnityEditor.serializedObject..ctor (UnityEngine.object[] objs) стирая сохраненные данные объекта.

ScriptableWizard

После написания класса необходимо добавить возможность инстанцировать объект DataHolder, создать ресурс в редакторе Unity. Можно воспльзоваться скриптом из статьи http://wiki.unity3d.com/CreateScriptableObjectAsset.

Или потратив чуть больше времени, написать удобный мастер для создания экземпляров DataHolder. В Unity для этого пердусмотрен класс ScriptableWizard.

Атрибут [MenuItem("Assets/Example/Create DataHolder")] добавляет возможность вызывать мастер DataHolderWizardExample по нажатию на правую кнопку мыши или из меню Assets.

Context menu Wizard

По нажатию на кнопку Create будет создан новый ресурс DataHolder с именем и данными заданными в мастере. Теперь эти ресурсы можно использовать в приложении для хранения и быстрого доступа к данным.

Created DataHolder assets

Продумайте структура данных ScriptableObject заранее, так как при изменении структуры придется обновлять код ScriptableWizard мастера. Например использование struct, поможет сгруппировать данные защитит их от непреднамеренного изменения в коде.

Инспектор

Созданные экземпляры DataHolder можно помещать в поля компонентов или списки, как обычные ресурсы (префабы) созданные из GameObject. Manager of DataHolders

Но, возникает небольшая проблема: как показано на скриншоте, данные DataHolder не видны, вместо них отображаются только имена ресурсов. Чтобы добавить отображение данных в инспекторе полей и списков можно написать скрипт расширяющий класс PropertyDrawer, но следует учесть ошибку в реализации метода FindPropertyRelativeдля ScriptableObject, он возвращает null вместо полей объекта.Для получения валидных SerializedProperty можно воспользоваться следующим кодом:

Manager of DataHolders with PropertyDrawer

Полный код примера работы с ScriptableObject можно найти в моем GIT репозитории: https://github.com/MerlinDS/ScriptableObjectExample