PropertyDrawer

class in UnityEditor

/

Inherits from:GUIDrawer

Switch to Manual

Description

用于从中派生自定义属性绘制器的基类。使用此基类可为您自己的 Serializable 类或者具有自定义 PropertyAttribute 的脚本变量创建自定义绘制器。

PropertyDrawer 有两种用途:
- 自定义 Serializable 类的每个实例的 GUI。
- 自定义具有自定义 PropertyAttribute 的脚本成员的 GUI。

如果您有自定义的 Serializable 类,可以使用 PropertyDrawer 来控制它在 Inspector 中的外观。 请参考以下脚本示例中的 Serializable 类 Ingredient:

using System;
using UnityEngine;

public 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; }

Using a custom PropertyDrawer, every appearance of the Ingredient class in the Inspector can be changed.

您可以使用 CustomPropertyDrawer 特性将 PropertyDrawer 附加到 Serializable 类,然后传入绘制器所对应的 Serializable 类的类型。

You can either use UIElements to build your custom PropertyDrawer or you can use IMGUI. To create a custom PropertyDrawer using UIElements, you have to override the PropertyDrawer.PropertyDrawer on the PropertyDrawer class. To create a custom PropertyDrawer using IMGUI, you have to override the PropertyDrawer.OnGUI on the PropertyDrawer class.

If the PropertyDrawer is used inside a UIElements-based inspector or EditorWindow, the UIElements implementation will be used if PropertyDrawer.PropertyDrawer is overwritten with a fallback on any IMGUI implementation. If the PropertyDrawer is used inside an IMGUI-based inspector or EditorWindow, only the IMGUI implementation will display. You cannot have UIElements running inside IMGUI.

Here's an example of a custom PropertyDrawer written using UIElements:

using UnityEditor;
using UnityEditor.UIElements;
using UnityEngine.UIElements;

// IngredientDrawerUIE [CustomPropertyDrawer(typeof(Ingredient))] public class IngredientDrawerUIE : PropertyDrawer { public override VisualElement CreatePropertyGUI(SerializedProperty property) { // Create property container element. var container = new VisualElement();

// Create property fields. var amountField = new PropertyField(property.FindPropertyRelative("amount")); var unitField = new PropertyField(property.FindPropertyRelative("unit")); var nameField = new PropertyField(property.FindPropertyRelative("name"), "Fancy Name");

// Add fields to the container. container.Add(amountField); container.Add(unitField); container.Add(nameField);

return container; } }

Here's an example of custom PropertyDrawer written using IMGUI. Compare the look of the Ingredient properties in the Inspector without and with a custom PropertyDrawer:


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

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(); } }

PropertyDrawer 的另一用途是改变脚本中具有自定义 PropertyAttribute 的成员的外观。 假如您要将脚本中的浮点数或整数限制在特定范围内,并在 Inspector 中将其显示为滑动条。 那么,您可以使用内置的 PropertyAttribute(名为 RangeAttribute)来执行此操作:

using UnityEngine;
using System.Collections;

public class ExampleClass : MonoBehaviour { // Show this float in the Inspector as a slider between 0 and 10 [Range(0.0F, 10.0F)] public float myFloat = 0.0F; }

您还可以创建自己的 PropertyAttribute。我们将以 RangeAttribute 的代码为例。 该特性必须扩展 PropertyAttribute 类。如果需要,属性可以使用参数并将它们存储为公共成员变量。

// This is not an editor script. The property attribute class should be placed in a regular script file.
using UnityEngine;

public class RangeAttribute : PropertyAttribute { public float min; public float max;

public RangeAttribute(float min, float max) { this.min = min; this.max = max; } }

Now that you have the attribute, you need to make a PropertyDrawer that draws properties that have that attribute. The drawer must extend the PropertyDrawer class, and it must have a CustomPropertyDrawer attribute to tell it which attribute it's a drawer for. Here's an example using IMGUI:

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

// Tell the RangeDrawer that it is a drawer for properties with the RangeAttribute. using UnityEngine; using UnityEditor;

[CustomPropertyDrawer(typeof(RangeAttribute))] public class RangeDrawer : PropertyDrawer { // Draw the property inside the given rect public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) { // First get the attribute since it contains the range for the slider RangeAttribute range = attribute as RangeAttribute;

// 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, Convert.ToInt32(range.min), Convert.ToInt32(range.max), label); else EditorGUI.LabelField(position, label.text, "Use Range with float or int."); } }

请注意,出于性能原因,EditorGUILayout 函数不能用于 PropertyDrawer。

另请参阅:PropertyAttribute 类、CustomPropertyDrawer 类。

Variables

attribute此属性的 PropertyAttribute。不适用于自定义类绘制器。(只读)
fieldInfo此属性所表示的成员的反射 FieldInfo。(只读)

Public Functions

CanCacheInspectorGUI重载此方法可确定您的属性的检视面板 GUI 是否可以缓存。
GetPropertyHeight重载此方法可指定此字段的 GUI 的高度(以像素为单位)。
OnGUIOverride this method to make your own IMGUI based GUI for the property.

Inherited members