Unity - 如何在Script中使用自己製作的PropertyAttribute

使用自己定義的Property並且在Inspector視窗中顯示自訂輸入格式。

  一般來說使用Unity的編輯器很方便,在類別裡建立一個Public的變數Unity就會自動把它序列化顯示在Inspector中可以編輯,而編輯這些數值基本上沒有太多的限制,也因此有可能會出現數值輸入出現意外的狀況,預防這種狀況一種就是在Script運作中加判斷,除此之外還可以在Inspector中就預先限制編輯人員可以輸入的範圍或是類別,也就是PropertyAttribute的方法。




  從上圖就可以簡單看出使用方式,在你要設定的變數上加上標籤,接著在Inspector中可以看到輸入方式我改為用Slider同時限制最大跟最小值。

  製作方式,首先建立一個類別繼承PropertyAttribute,這個是設定標籤屬性格式的地方,例如[MyAttribute(1, 100)]設定兩個參數,這邊我設定第一個參數是作為限制最小值使用,第二個參數作為限制最大值使用。這邊要怎麼設定,就看你自己的需求,例如一個string一個int作為限制字串長度使用的標籤等等。
public class MyAttribute : PropertyAttribute {
    public readonly int max;
    public readonly int min;

    public MyAttribute(int min, int max) {
        this.min = min;
        this.max = max;
    }
}


  接著再建立一個新的Class繼承PropertyDrawer,這個類別主要功能在於控制該Property在Inspector中顯示的方式,以及可以在這邊做一些條件判斷等等。
[CustomPropertyDrawer(typeof(MyAttribute))]
public class MyDrawer : PropertyDrawer {

    //建立一個attribute reference的Getter
    MyAttribute myAttribute { get { return ((MyAttribute)attribute); } }

    //設定PropertyDrawer的高
    public override float GetPropertyHeight (SerializedProperty property, GUIContent label) {
        return base.GetPropertyHeight (property, label);
    }

    //Inspector中顯示的地方,Inspector中輸入的數值可以從property裡面取得,這邊因為是輸入數值,所以用property.intValue取得整數。
    public override void OnGUI (Rect position, SerializedProperty property, GUIContent label) {
        EditorGUI.BeginProperty (position, label, property);

        var indent = EditorGUI.indentLevel;
        EditorGUI.indentLevel = 0;

        //取得property輸入的值(property.intValue),並且使用attribute設定的最大最小來作為範圍。
        //同時這邊使用IntSlider來讓Inspector中出現SliderBar讓編輯者調整。
        property.intValue = EditorGUI.IntSlider (position, label, property.intValue, myAttribute.min, myAttribute.max);

        EditorGUI.indentLevel = indent; 
        EditorGUI.EndProperty ();
    }
}

  最後要使用的話就如圖片中的方式,在整數型別變數上加上這個標籤即可,把這個Component掛在gameobject上就可以在Inspector中編輯了。
public class MyScript : MonoBehaviour {
    [MyAttribute(1, 100)]
    public int myValue;
}

3 comments:

asen said...
This comment has been removed by the author.
asen said...

這跟[Range]有甚麼差別

IVerv said...

如果功能一樣當然沒什麼差別,但這篇主要不是在製作功能,在Script中使用PropertyAttribute也不是只有[Range]這一個目的

Post a Comment