Unity编辑器开发CustomPropertyDrawer

  在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方法,我们通过重写这个方法,修改属性显示;
image

创建Editor文件夹

 第一步,我先创建一个Editor文件夹,告诉Unity这里面放与编辑器有关的代码。不会参与游戏的构建。接下来,创建一个C#文件,命名为FloatRangeDrawer,在这里写修改FloatRange类型在编辑器中显示的相关代码。
image

继承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.BeginPropertyEditorGUI.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();

image

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"));

image

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"));

这样我们自定义属性列表就做好啦
image

posted @ 2021-05-06 01:17  小小肥宅  阅读(1184)  评论(1编辑  收藏  举报