カスタムプロパティードローワーの基底クラスです。作成した Serializable クラスや PropertyAttribute 変数のカスタムドローワーを作成して使用することができます。
PropertyDrawers have two uses: Customize the GUI of every instance of a Serializable class. PropertyAttribute の付いたスクリプトメンバーの GUI をカスタマイズ If you have a custom Serializable class, you can use a PropertyDrawer to control how it looks in the Inspector. Consider the Serializable class Ingredient in the script below:
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; }
PropertyDrawer を使用すると、Ingredient クラスの状況によってインスペクターを変更することが可能です。
PropertyDrawer は CustomPropertyDrawer 属性とドローワーを使用する Serializable クラスの型をアタッチします。
You can either use UI Toolkit to build your custom PropertyDrawer or you can use IMGUI. To create a custom PropertyDrawer using UI Toolkit, you have to override the PropertyDrawer.CreatePropertyGUI on the PropertyDrawer class. To create a custom PropertyDrawer using IMGUI, you have to override the PropertyDrawer.OnGUI on the PropertyDrawer class.
**Note**: You cannot have UI Toolkit running inside IMGUI, which means that if your custom PropertyDrawer only has a UI Toolkit implementation, it will not work inside an IMGUI custom Inspector or a parent IMGUI custom PropertyDrawer. In Unity 2022.2 and above, the default Inspector uses UI Toolkit exclusively in custom PropertyDrawers. Prior to 2022.2, it is recommended that you either implement both IMGUI and UI Toolkit versions of each PropertyDrawer, or make sure they are exclusively used inside custom UI Toolkit inspectors.
Here's an example of a custom PropertyDrawer written using UI Toolkit:
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 - pass 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 の付いたメンバーの外観を変更することができます。 例えば整数で特定の範囲内で値を設定したい場合に、インスペクターにはスライダーとして表示することができます。 これは RangeAttribute としてビルドインされている PropertyAttribute 機能でこのように使用します。
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 を使用できないことに注意してください。
Note: Lists and arrays are handled differently with custom drawers. When the SerializedProperty
is passed to the CreatePropertyGUI
method, it represents each item in the list. However, when the custom drawing is needed for the list itself, you must wrap the property accordingly.
If you need your property drawer to perform cleanup tasks, such as detaching itself from editor events, you can implement the IDisposable interface. This interface allows you to define a method that will be invoked when the Editor is being destroyed, giving you the opportunity to handle any necessary cleanup operations.
関連項目: PropertyAttribute クラス、CustomPropertyDrawer クラス
attribute | プロパティーの PropertyAttribute を取得します(読み取り専用) |
fieldInfo | このプロパティーが表すメンバーのリフレクション FieldInfo (読み取り専用) |
preferredLabel | The label for this property. (Read Only) |
CreatePropertyGUI | Creates custom GUI with UI Toolkit for the property. |
GetPropertyHeight | ピクセル単位で GUI の高さを設定します そのためにはこのメソッドをオーバーライドしてください |
OnGUI | Override this method to make your own IMGUI based GUI for the property. |
Did you find this page useful? Please give it a rating:
Thanks for rating this page!
What kind of problem would you like to report?
Thanks for letting us know! This page has been marked for review based on your feedback.
If you have time, you can provide more information to help us fix the problem faster.
Provide more information
You've told us this page needs code samples. If you'd like to help us further, you could provide a code sample, or tell us about what kind of code sample you'd like to see:
You've told us there are code samples on this page which don't work. If you know how to fix it, or have something better we could use instead, please let us know:
You've told us there is information missing from this page. Please tell us more about what's missing:
You've told us there is incorrect information on this page. If you know what we should change to make it correct, please tell us:
You've told us this page has unclear or confusing information. Please tell us more about what you found unclear or confusing, or let us know how we could make it clearer:
You've told us there is a spelling or grammar error on this page. Please tell us what's wrong:
You've told us this page has a problem. Please tell us more about what's wrong:
Thank you for helping to make the Unity documentation better!
Your feedback has been submitted as a ticket for our documentation team to review.
We are not able to reply to every ticket submitted.