Version: 2019.3
Окна редактора (Editor Windows)
Пользовательские редакторы (Custom Editors)

Property Drawers

Property Drawers можно использовать для того, чтобы настроить внешний вид определённых элементов управления в инспекторе (Inspector), используя атрибуты ваших скриптов или настроив то, как определённый Serializable (сериализуемый) класс должен выглядеть.

У Property Drawers есть 2 применения:

  • Настройка интерфейса каждого экземпляра сериализуемого класса.

Настройка интерфейса member переменных скрипта используя атрибуты свойства (Property Attributes)

Настройка интерфейса сериализуемого класса

Если у вас есть пользовательский сериализуемый (Serializable) класс, то вы можете использовать Property Drawer для того, чтобы управлять его внешним видом в инспекторе. Рассмотрим сериализуемый класс Ingredient в скрипте ниже:

C# (example):

using System;
using UnityEngine;

enum IngredientUnit { Spoon, Cup, Bowl, Piece }

// Custom serializable class
[Serializable]
public class Ingredient
{
    public string name;
    public int amount = 1;
    public IngredientUnit unit;
}

public class Recipe : MonoBehaviour
{
    public Ingredient potionResult;
    public Ingredient[] potionIngredients;
}

Используя пользовательский Property Drawer, каждый вариант внешнего вида класса Ingredient в инспекторе может быть изменён. Сравните внешний вид и свойства класса Ingredient в инспекторе без и с пользовательским Property Drawer:

Class in the Inspector without (left) and with (right) custom Property Drawer.
Class in the Inspector without (left) and with (right) custom Property Drawer.

Вы можете присоединить Property Drawer к сериализуемому классу, используя атрибут CustomPropertyDrawer, и передать тип сериализуемого класса, для которого используется Property Drawer.

C# (example):

using UnityEditor;
using UnityEngine;

// IngredientDrawer
[CustomPropertyDrawer(typeof(Ingredient))]
public class IngredientDrawer : PropertyDrawer
{
    // Draw the property inside the given rect
    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    {
        // Using BeginProperty / EndProperty on the parent property means that
        // prefab override logic works on the entire property.
        EditorGUI.BeginProperty(position, label, property);

        // Draw label
        position = EditorGUI.PrefixLabel(position, GUIUtility.GetControlID(FocusType.Passive), label);

        // Don't make child fields be indented
        var indent = EditorGUI.indentLevel;
        EditorGUI.indentLevel = 0;

        // Calculate rects
        var amountRect = new Rect(position.x, position.y, 30, position.height);
        var unitRect = new Rect(position.x + 35, position.y, 50, position.height);
        var nameRect = new Rect(position.x + 90, position.y, position.width - 90, position.height);

        // Draw fields - passs GUIContent.none to each so they are drawn without labels
        EditorGUI.PropertyField(amountRect, property.FindPropertyRelative("amount"), GUIContent.none);
        EditorGUI.PropertyField(unitRect, property.FindPropertyRelative("unit"), GUIContent.none);
        EditorGUI.PropertyField(nameRect, property.FindPropertyRelative("name"), GUIContent.none);

        // Set indent back to what it was
        EditorGUI.indentLevel = indent;

        EditorGUI.EndProperty();
    }
}

Настройка интерфейса member переменных скрипта используя атрибуты свойства (Property Attributes)

Другим вариантом использования Property Drawer является изменение внешнего вида элементов в скрипте, у которых выставлены пользовательские атрибуты свойства (Property Attributes). Например, вы желаете ограничить значения float или integer в определённом диапазоне и отобразить их в виде ползунков в инспекторе. Используя встроенный атрибут свойства (PropertyAttribute), который называется RangeAttribute, вы можете сделать это так:

C# (example):

// Show this float in the Inspector as a slider between 0 and 10
[Range(0f, 10f)]
float myFloat = 0f;

Кроме того вы можете сделать собственный атрибут свойства. Мы используем код для RangeAttribute в качестве примера. Атрибут должен наследоваться из класса PropertyAttribute. Если вы захотите, то ваше свойство сможет брать параметры и хранить их как public member переменные.

C# (example):

using UnityEngine;

public class MyRangeAttribute : PropertyAttribute 
{
        readonly float min;
        readonly float max;
        
        void MyRangeAttribute(float min, float max)
        {
            this.min = min;
            this.max = max;
        }
}

Теперь, когда у вас есть атрибут, вам надо приказать Property Drawer рисовать свойства, у которых есть этот атрибут. Drawer должен унаследовать класс PropertyDrawer и у него должен быть атрибут CustomPropertyDrawer, чтобы знать, для какого атрибута этот Property Drawer.

The property drawer class should be placed in an editor script, inside a folder called Editor.

C# (example):

using UnityEditor;
using UnityEngine;

// Tell the MyRangeDrawer that it is a drawer for properties with the MyRangeAttribute.
[CustomPropertyDrawer(typeof(MyRangeAttribute))]
public class RangeDrawer : PropertyDrawer
{
    // Draw the property inside the given rect
    void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    {
        // First get the attribute since it contains the range for the slider
        MyRangeAttribute range = (MyRangeAttribute)attribute;

        // Now draw the property as a Slider or an IntSlider based on whether it's a float or integer.
        if (property.propertyType == SerializedPropertyType.Float)
            EditorGUI.Slider(position, property, range.min, range.max, label);
        else if (property.propertyType == SerializedPropertyType.Integer)
            EditorGUI.IntSlider(position, property, (int) range.min, (int) range.max, label);
        else
            EditorGUI.LabelField(position, label.text, "Use MyRange with float or int.");
    }
}

Учтите, что по причинам производительности, функции EditorGUILayout не пригодны для использования с Property Drawers.

Окна редактора (Editor Windows)
Пользовательские редакторы (Custom Editors)