在unity中我們有時候需要自定義結構類型,比如我們自定義一個結構浮點數的范圍FloatRange,在最大和最小的范圍中取隨機數。
using UnityEngine;
[System.Serializable]
public struct FloatRange
{
public float min, max;
public float RangeValueInRange
{
get
{
return Random.Range(min, max);
}
}
}
如果我們想設置一個FloatRange類型的字段,在編輯器中可能會顯示成這樣。但是一個屬性占了兩行,不太美觀,我們可以自己修改編輯器,Unity編輯器顯示字段時,會調用OnGUI方法,我們通過重寫這個方法,修改屬性顯示;
創建Editor文件夾
第一步,我先創建一個Editor文件夾,告訴Unity這里面放與編輯器有關的代碼。不會參與游戲的構建。接下來,創建一個C#文件,命名為FloatRangeDrawer,在這里寫修改FloatRange類型在編輯器中顯示的相關代碼。
繼承PropertyDrawer
對編輯器屬性操作,需要繼承PropertyDrawer類,同時還依賴UnityEditor命名空間。類名上加上[CustomPropertyDrawer(typeof(FloatRange))],告訴Unity這是一個CustomPropertyDrawer,並且typeof(FloatRange)指定是FloatRange類型的CustomPropertyDrawer;
using UnityEngine;
using UnityEditor;//編輯器依賴
//告訴Unity要創建FloatRange類型的CustomPropertyDrawer
[CustomPropertyDrawer(typeof(FloatRange))]
public class FloatRangeDrawer : PropertyDrawer
{
}
具體代碼
1.重寫Unity本身onGUI的函數,里面分別帶有位置,屬性和標簽三個參數。EditorGUI.BeginProperty和EditorGUI.EndProperty告訴Unity要創建屬性的UI,在這兩個方法之間寫我們的代碼
//覆蓋Unity本身OnGUI函數,它在每次要顯示FloatRange時被調用。
//三個參數 position 定義繪制的區域 property 定義浮點數的范圍值
//label使用的默認標簽
public override void OnGUI(
Rect position, SerializedProperty property, GUIContent label
){
EditorGUI.BeginProperty(position, label, property);
EditorGUI.EndProperty();
}
2.通過EditorGUI.PropertyField方法顯示我們的屬性UI,方法有兩個參數,一個是顯示的位置,一個是屬性,可以通過 property.FindPropertyRelative("屬性名")獲取屬性
EditorGUI.BeginProperty(position, label, property);
EditorGUI.PropertyField(position, property.FindPropertyRelative("min"));
EditorGUI.PropertyField(position, property.FindPropertyRelative("max"));
EditorGUI.EndProperty();
現在我們編輯器里已經顯示了min和max兩個屬性了,但是因為他們的位置都是position,所以重疊在一起了,我們把兩個屬性的寬度都縮小一半,然后將其中一個屬性的位置后移自身的寬度。這樣兩個屬性就並排顯示了
EditorGUI.BeginProperty(position, label, property);
//區域寬度設為一半
position.width = position.width / 2f;
EditorGUI.PropertyField(position, property.FindPropertyRelative("min"));
//max屬性右移
position.x += position.width;
EditorGUI.PropertyField(position, property.FindPropertyRelative("max"));
EditorGUI.EndProperty();
3.現在屬性的Label太寬了,我們可以通過EditorGUIUtility.labelWidth進行調整
EditorGUI.BeginProperty(position, label, property);
//區域寬度設為一半
position.width = position.width / 2f;
//調整標簽Label寬度為 當前寬度的一半
EditorGUIUtility.labelWidth = position.width / 2f;
EditorGUI.PropertyField(position, property.FindPropertyRelative("min"));
//max屬性右移
position.x += position.width;
EditorGUI.PropertyField(position, property.FindPropertyRelative("max"));
4.現在很好,但是別忘了我們的字段標簽; EditorGUI.PrefixLabel方法設置字段標簽,返回值是添加字段標簽后剩余的位置
EditorGUI.BeginProperty(position, label, property);
//顯示字段標簽,返回標簽占用后剩余的區域
position = EditorGUI.PrefixLabel(position, label);
//區域寬度設為一半
position.width = position.width / 2f;
//調整標簽Label寬度為 當前寬度的一半
EditorGUIUtility.labelWidth = position.width / 2f;
EditorGUI.PropertyField(position, property.FindPropertyRelative("min"));
//max屬性右移
position.x += position.width;
EditorGUI.PropertyField(position, property.FindPropertyRelative("max"));
這樣我們自定義屬性列表就做好啦