一:前言
PropertyDrawer允许我们自定义一个属性在Inspector面板的如何绘制
二:注意事项
——PropertyDrawer只对可序列化的类有效 ——OnGUI方法里只能使用GUI相关方法(使用EditorGUI绘制),不能使用Layout相关方法
三:代码实现
需要两个类 ——定义一个类,继承自PropertyAttribute,为了添加Header时才调用此特性(如果不需要Header则不用定义) ——定义一个类,继承自PropertyDrawer,为了绘制此属性
OnGUI:重写此方法可以自定义此字段在面板上如果绘制。position坐标是从左上角开始 GetPropertyHeight:重写此方法可以指定此字段的GUI像素高度(默认是18)
四:案例——模拟内置的Range特性
using UnityEngine;
using UnityEditor;
using System;
public sealed class TestRangeAttribute : PropertyAttribute
{
public readonly float min;
public readonly float max;
public TestRangeAttribute(float min, float max)
{
this.min = min;
this.max = max;
}
}
[CustomPropertyDrawer(typeof(TestRangeAttribute))]
public class TestRangeDrawer : PropertyDrawer
{
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
TestRangeAttribute range = attribute as TestRangeAttribute;
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, "error");
}
}
}
五:案例——自定义特性
创建一个自定义的Time特性,可以显示转换成的天、时、分、秒
using UnityEngine;
using UnityEditor;
public sealed class TimeAttribute : HeaderAttribute
{
public bool showDay;
public bool showHour;
public bool showMin;
public bool showSec;
public TimeAttribute(bool showDay = false, bool showHour = false, bool showMin = false, bool showSec = false)
{
this.showDay = showDay;
this.showHour = showHour;
this.showMin = showMin;
this.showSec = showSec;
}
}
[CustomPropertyDrawer(typeof(TimeAttribute))]
public class TimeAttributeDrawer : PropertyDrawer
{
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
EditorGUI.PropertyField(new Rect(position.x, position.y, position.width * 0.6f, position.height), property);
EditorGUI.LabelField(new Rect(position.x + position.width * 0.6f, position.y, position.width * 0.4f, position.height), GetTimeString(property.floatValue));
}
string GetTimeString(float sec)
{
TimeAttribute target = attribute as TimeAttribute;
if (target.showDay)
{
int day = (int)(sec / (60 * 60 * 60));
return $"{day}天";
}
else if (target.showHour)
{
int hour = (int)(sec / (60 * 60));
return $"{hour}小时";
}
else if (target.showMin)
{
int min = (int)(sec / 60);
return $"{min}分钟";
}
else if (target.showSec)
{
return $"{sec}秒";
}
else
{
return "";
}
}
}
|