Property Drawer を利用すると、スクリプトの属性を使用したり、特定の Serializable
クラスの外観を操作することによって、インスペクターウィンドウ の一部の GUI をカスタマイズできます。
Property Drawer には 2 つの使い方があります。
カスタムの Serializable のクラスがある場合、それが インスペクター でどのように見えるかを制御する Property Drawer を使用できます。以下のサンプルスクリプトの Serializable クラスの Ingredient に注意して考えてみてください。(ノート: これらはエディタースクリプトではありません。Property Attribute クラスは通常のスクリプトファイルに置いてください。)
C# (例)
using System;
using UnityEngine;
enum IngredientUnit { Spoon, Cup, Bowl, Piece }
// カスタムの Serializable クラス
[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 が有る場合、または無い場合の外観を比較してみてください。
CustomPropertyDrawer 属性を使用して Serializable クラスに Property Drawer を付け、それがドローワー (drawer) である Serializable クラスの型を渡すことができます。
C# (例)
using UnityEditor;
using UnityEngine;
// IngredientDrawer
[CustomPropertyDrawer(typeof(Ingredient))]
public class IngredientDrawer : PropertyDrawer
{
// 指定された矩形内のプロパティーを描画
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
// 親プロパティーで BeginProperty / EndProperty を使用することは、
// プレハブオーバーライドロジックがプロパティー全体で機能することを意味します。
EditorGUI.BeginProperty(position, label, property);
// ラベルを描画
position = EditorGUI.PrefixLabel(position, GUIUtility.GetControlID(FocusType.Passive), label);
// 子のフィールドをインデントしない
var indent = EditorGUI.indentLevel;
EditorGUI.indentLevel = 0;
// 矩形を計算
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);
// フィールドを描画 - GUIContent.none をそれぞれに渡すと、ラベルなしに描画されます
EditorGUI.PropertyField(amountRect, property.FindPropertyRelative("amount"), GUIContent.none);
EditorGUI.PropertyField(unitRect, property.FindPropertyRelative("unit"), GUIContent.none);
EditorGUI.PropertyField(nameRect, property.FindPropertyRelative("name"), GUIContent.none);
// インデントを元通りに戻します
EditorGUI.indentLevel = indent;
EditorGUI.EndProperty();
}
}
Property Drawer の他の使い道は、カスタムの Property Attributes を持っているスクリプト内のメンバーの外観を変更することです。例えば、スクリプトの float 型や int 型を特定の範囲に制限し、インスペクター のスライダーとしてそれらを表示したいとします。RangeAttribute と呼ばれるビルトインの PropertyAttribute を使って、以下のように行うことができます。
C# (例)
// float をインスペクター内で範囲が 0 から 10 のスライダーとして表示します
[Range(0f, 10f)]
float myFloat = 0f;
同様ににて、独自の PropertyAttribute を作ることができます。例として RangeAttribute のコードを使用します。属性は PropertyAttribute クラスを拡張する必要があります。好みに応じて、プロパティーはパラメーターを取り、パブリックのメンバー変数としてそれらを格納できます。
C# (例)
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 を作成する必要があります。ドローワーは PropertyDrawer クラスを拡張する必要があり、どの属性のドローワーであるかを伝えるために CustomPropertyDrawer 属性を持つ必要があります。
Property Drawer クラスは Editor と呼ばれるフォルダー内のエディタースクリプトに置きます。
C# (例)
using UnityEditor;
using UnityEngine;
// MyRangeDrawer に、それが MyRangeAttribute を持つプロパティーのドローワーであることを伝えます
[CustomPropertyDrawer(typeof(MyRangeAttribute))]
public class RangeDrawer : PropertyDrawer
{
// 指定した矩形内にプロパティーを描画
void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
// スライダーの範囲情報を持っているので、最初に属性を取得します
MyRangeAttribute range = (MyRangeAttribute)attribute;
// プロパティーが float か int かによって、Slider または IntSlider を描画します
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 Drawer では使用できないことを注意してください。
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.