在上一篇文章中提到,CustomEditor只能自定义单一类,被其他类持有的类自定义没有作用,这个时候就需要使用CustomPropertyDrawer属性。
PropertyDrawer用于自定义属性绘制器的基类。使用PropertyDrawer来控制它在Inspector中的样式。可以使用CustomPropertyDrawer 特性将 PropertyDrawer附加到 Serializable类,然后传入绘制器进行渲染。使用此基类有两种用途:
[Serializable]
的自定义类,可以自定义绘制实例的GUI。[Range(0f, 10f)]
[CustomPropertyDrawer(typeof(MonoTest))]
public class MonoTestEditor : PropertyDrawer
{
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
var nameRect = new Rect(position.x, position.y, 222, position.height);
var amountRect = new Rect(position.x + 222, position.y, 222, position.height);
var unitRect = new Rect(position.x + 222 + 222, position.y, 222, position.height);
EditorGUIUtility.labelWidth = 100;
EditorGUI.PropertyField(nameRect, property.FindPropertyRelative("intValue"));
EditorGUI.PropertyField(amountRect, property.FindPropertyRelative("boolValue"));
EditorGUI.PropertyField(unitRect, property.FindPropertyRelative("enumValue"));
}
}
Unity中,有一些内置属性可直接使用,例如:[Range(0,100)]
、[Header(“Header Name”)]
、[Tooltip(“Tips”)]
等,当然自己也可以自定义属性,一个简单实例(仅做示例,不论功能):需要在滑动条后面,显示当前滑动条的值
代码如下:
//定义自定义属性类
public sealed class RangeTestAttribute : PropertyAttribute
{
public readonly float min;
public readonly float max;
public RangeTestAttribute(float min, float max)
{
this.min = min;
this.max = max;
}
}
//对属性类自定义显示
[CustomPropertyDrawer(typeof(RangeTestAttribute))]
public class RangeTestAttributeDrawer : PropertyDrawer
{
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
RangeTestAttribute range = (RangeTestAttribute)attribute;
//类型是float
if (property.propertyType == SerializedPropertyType.Float)
{
EditorGUI.Slider(new Rect(position.x, position.y, position.width * 0.8f, position.height), property, range.min, range.max);
EditorGUI.LabelField(new Rect(position.x + position.width * 0.8f, position.y, position.width - (position.x + position.width * 0.8f), position.height), "滑到了" + property.floatValue);
}
else
{
EditorGUI.HelpBox(new Rect(position.x, position.y, position.width, position.height), "只支持float类型属性", MessageType.Error);
}
}
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
return base.GetPropertyHeight(property, label);
}
}
结果
我们仿照Unity内置的Range,自定义一个属性,以后咱们就可以使用代码[RangeTest(-1, 100)]
,来使用属性功能(在后面跟了一个小尾巴,显示当前滑动条的数值)。如下:
//[Range(-1, 100)]
[RangeTest(-1, 100)]
public float enumValue;