Все вводимые в инспекторе данные надо проверять на корректность.
И Unity это делает. В частности сверяет тип вводимых данных с типом переменной, которой они будут присвоены.
Например в поле типа int нельзя ввести текст или десятичное число.
А если нам нужны дополнительные проверки?
Есть у нас, к примеру, такой класс:
using UnityEngine;
public class Unit : MonoBehaviour
{
[SerializeField]
private string _name = "NoName";
public string unitName
{
get{return _name;}
set
{
_name = value;
if(string.IsNullOrEmpty(_name))
_name = "NoName";
}
}
[SerializeField]
private int _price = 10;
public int price
{
get{return _price;}
set
{
_price = value;
if(_price < 1)
_price = 1;
}
}
[SerializeField]
private float _health = 100f;
public float health
{
get{return _health;}
set
{
_health = Mathf.Clamp(value, 0f, 100f);
}
}
//...code...
}
В свойствах есть проверки, и это отлично работает в коде:
unit.unitName = ""; //Присвоит "NoName"
unit.price = -10; //Присвоит 1
unit.health = 1000; //Присвоит 100
Но совершенно не мешает указать некорректные данные в редактореЧтобы донести проверку до редактора Unity используем CustomEditor.
Создадим скрипт с наследованием от класса Editor (пространство имён UnityEditor).
Все скрипты редактора должны быть в папке "Editor".
Точная иерархия не важна, главное, чтобы в пути была папка "Editor".
using UnityEditor;
using UnityEngine;
[CustomEditor(typeof(Unit))]
public class UnitEditor : Editor
{
public override void OnInspectorGUI()
{
DrawDefaultInspector();
}
}
Имя класса редактора для Unity значения не имеет, но для удобства используется ИмяКомпонентаEditorВ атрибуте [CustomEditor] указывается класс, для которого предназначен данный редактор.
Метод "OnInspectorGUI" вызывается при обновлении инспектора.
"DrawDefaultInspector" - отрисовка стандартного инспектора для нашего класса.
Unity и без нас делает это по-умолчанию. Нам же нужно внедрить проверку данных, поэтому вместо "DrawDefaultInspector" пишем свой вариант.
Для начала нам нужно получить компонент, который мы редактируем (тот, который сейчас висит на выбранном объекте).
Он хранится в переменной "target".
Unit unit = target as Unit;
Но вставлять это в "OnInspectorGUI" мы не будем. Нам не нужно получать компонент каждый апдейт инспектора.Лучше объявим приватную переменную в нашем скрипте редактора и получим компонент в событии "OnEnable".
Событие "OnEnable" в скриптах редактора вызывается при выборе объекта, на котором висит редактируемый компонент.
private Unit _unit = null;
void OnEnable()
{
_unit = target as Unit;
}
Отлично. Теперь у нас есть ссылка на компонент, можно приступать к написанию инспектора с проверками.Для отрисовки полей будем использовать класс EditorGUILayout. (Можно использовать и GUILayout, если нужных элементов нет в GUI редактора).
В случае использования Layout элементы GUI идут друг за другом и нам не нужно расчитывать их точное положение.В "OnInspectorGUI" выводим наши поля:
_unit.unitName = EditorGUILayout.TextField("Name", _unit.unitName);
_unit.price = EditorGUILayout.IntField("Price", _unit.price);
_unit.health = EditorGUILayout.FloatField("Health", _unit.health);
Все необходимые проверки проводятся в свойствах при присвоении значения.