В прошлой статье мы рассмотрели проверку вводимых данных через свойства класса.
Но в случае с публичными свойствами, значения переменных можно изменить из любого класса, а это не всегда хорошо.
Чтобы этого избежать, можно сделать свойства приватными или убрать вовсе, но в этом случае и редактор потеряет к ним доступ и посыплет ошибками.
К счастью редактор имеет доступ к сериализуемым полям, это все публичные переменные и приватные с соответствующим атрибутом.
Приступим к изменению класса редактора из прошлой статьи.
После удаления всего неработающего и ненужного, класс примет такой вид:
using UnityEditor;
using UnityEngine;
[CustomEditor(typeof(Unit))]
public class UnitEditor : Editor
{
void OnEnable()
{
}
public override void OnInspectorGUI()
{
}
}
Доступ к редактируемому компоненту мы теперь будем получать через свойство "serializedObject".
Необходимые поля класса можно получить с помощью функции "FindProperty", которая принимает имя переменной и возвращает объект типа "SerializedProperty".
Создадим переменные для хранения наших полей и получим их в функции "OnEnable" (Да-да, это чтобы не искать их каждое обновление инспектора).
private SerializedProperty _name = null;
private SerializedProperty _price = null;
private SerializedProperty _health = null;
void OnEnable()
{
_name = serializedObject.FindProperty ("_name");
_price = serializedObject.FindProperty ("_price");
_health = serializedObject.FindProperty ("_health");
}
Для отображения полей используем знакомый нам класс "EditorGUILayout", но уже с помощью "PropertyField".При использовании PropertyField, Unity самостоятельно определяет тип переменной и выводит соответствующее поле, применяя все атрибуты кастомизации, указанные для данной переменной.
public override void OnInspectorGUI()
{
EditorGUILayout.PropertyField (_name);
EditorGUILayout.PropertyField (_price);
EditorGUILayout.PropertyField (_health);
}
Теперь нужно добавить необходимые проверки.Получение значений осушествляется через свойства "типValue"
public override void OnInspectorGUI()
{
EditorGUILayout.PropertyField (_name);
if (string.IsNullOrEmpty (_name.stringValue))
_name.stringValue = "NoName";
EditorGUILayout.PropertyField (_price);
if (_price.intValue < 1)
_price.intValue = 1;
EditorGUILayout.PropertyField (_health);
_health.floatValue = Mathf.Clamp (_health.floatValue, 0f, 100f);
}
Всё прекрасно отображается, и проверки работают. Но стоит запустить сцену или переключиться на другой объект, как всё сбрасывается.Происходит это потому что изменения не применены к объекту.
Исправим это, добавив в конце функции "OnInspectorGUI":
//Применение изменений
serializedObject.ApplyModifiedProperties ();
Отлично, изменения сохраняются, но чрезмерно часто. Мы заставляем Unity применять изменения, даже когда их нет.Нам нужно проверять, были ли изменения, и если они были, то применять. Для этого используем методы "BeginChangeCheck" и "EndChangeCheck" из класса "EditorGUI".
EndChangeCheck возвращает true, если были изменены значения полей редактора, указанных между BeginChangeCheck и EndChangeCheck
public override void OnInspectorGUI()
{
EditorGUI.BeginChangeCheck ();
EditorGUILayout.PropertyField (_name);
if (string.IsNullOrEmpty (_name.stringValue))
_name.stringValue = "NoName";
EditorGUILayout.PropertyField (_price);
if (_price.intValue < 1)
_price.intValue = 1;
EditorGUILayout.PropertyField (_health);
_health.floatValue = Mathf.Clamp (_health.floatValue, 0f, 100f);
if (EditorGUI.EndChangeCheck ())
{
//Применение изменений
serializedObject.ApplyModifiedProperties();
}
}
На этом всё :)