目录 1. 前言 2. PropertyDrawer 2.1 参数总览 2.2 两种用途 2.3 注意事项 2.4 代码样例 3. PropertyDrawer与PropertyAttribute结合使用
1. 前言
在Unity中,PropertyDrawer 和PropertyAttribute 是两个重要的工具,它们主要用于自定义属性的显示和行为。 PropertyDrawer 是一个类,它定义了如何在编辑器中渲染属性的外观。你可以通过继承PropertyDrawer 类并重写其方法来自定义属性的显示方式。PropertyDrawer 主要关注的是在编辑器中如何显示属性,提供了一种灵活的方式来控制属性的外观和交互方式。PropertyAttribute 是一个标记特性,它可以应用于C#类中的字段或属性上,提供额外的元数据或改变默认的编辑行为。通过使用PropertyAttribute ,你可以为属性添加各种功能,例如限制值的范围、添加提示信息等。PropertyAttribute 主要关注的是在代码中提供更多关于属性的信息和行为,以便在编辑器中更好地处理和呈现这些属性。将PropertyDrawer 和PropertyAttribute 结合使用,可以实现更加丰富和灵活的编辑器自定义功能。通过定义自己的PropertyDrawer 来控制属性的显示方式,并使用PropertyAttribute来提供额外的属性和行为信息,可以创建出高度定制化的编辑器界面,满足特定场景的需求。
2. PropertyDrawer
2.1 参数总览
常用参数 描述 CreatePropertyGUI 使用 UI Toolkit 为属性创建自定义 GUI。 GetPropertyHeight 重载此方法可指定此字段的 GUI 的高度(以像素为单位)。 OnGUI 重写此方法,为属性创建自己的基于 IMGUI 的 GUI。
2.2 两种用途
自定义可序列化类的每个实例的GUI。如果脚本中的属性是自定义类,并且需要在Inspector中显示,可以使用Serializable修饰符。 自定义具有自定义PropertyAttribute的脚本成员的GUI。通过结合使用PropertyAttribute和PropertyDrawer,可以自定义自己的Attribute,如添加提示信息、范围限制等。
2.3 注意事项
PropertyDrawer 只对可序列化的类有效,非可序列化的类没法在Inspector面板中显示。OnGUI 方法里只能使用GUI相关方法,不能使用Layout相关方法。PropertyDrawer 对应类型的所有属性的显示方式都会修改,例如创建一个带string属性的MonoBehaviour。
2.4 代码样例
using UnityEngine ;
using UnityEditor ; [ CustomPropertyDrawer ( typeof ( string ) ) ]
public class StringPropertyDrawer : PropertyDrawer
{ public override void OnGUI ( Rect position, SerializedProperty property, GUIContent label) { Rect btnRect = new Rect ( position) ; position. width -= 60 ; btnRect. x += btnRect. width - 60 ; btnRect. width = 60 ; EditorGUI. BeginProperty ( position, label, property) ; EditorGUI. PropertyField ( position, property, true ) ; if ( GUI. Button ( btnRect, "select" ) ) { string path = property. stringValue; string selectStr = EditorUtility. OpenFilePanel ( "选择文件" , path, "" ) ; if ( ! string . IsNullOrEmpty ( selectStr) ) { property. stringValue = selectStr; } } EditorGUI. EndProperty ( ) ; }
}
using UnityEngine ; public class Test : MonoBehaviour
{ public string str;
}
为Inspector面板中的所有string属性添加一个选择文件按钮,选中文件的路径直接赋值给该变量。
3. PropertyDrawer与PropertyAttribute结合使用
想要修改部分类的指定类型的属性的显示,直接使用PropertyDrawer 就无法满足条件,这时可以结合PropertyDrawer 和PropertyAttribute 来实现需求。 Unity中,有一些内置属性可直接使用,例如:[Range(0,100)] 、[Header(“Header Name”)] 、[Tooltip(“Tips”)] 等,当然自己也可以自定义属性,以下是一个简单实例:需要在滑动条后面,显示当前滑动条的值。
using UnityEngine ; public class Test : MonoBehaviour
{ [ Range ( 0.0F , 10.0F ) ] public float myFloat = 0.0F ;
}
using UnityEngine ; public class RangeAttribute : PropertyAttribute
{ public float min; public float max; public RangeAttribute ( float min, float max) { this . min = min; this . max = max; }
}
using UnityEngine ;
using UnityEditor ;
using System ; [ CustomPropertyDrawer ( typeof ( RangeAttribute ) ) ]
public class RangeDrawer : PropertyDrawer
{ public override void OnGUI ( Rect position, SerializedProperty property, GUIContent label) { RangeAttribute range = attribute as RangeAttribute ; 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 if ( property. propertyType == SerializedPropertyType. Integer) EditorGUI. IntSlider ( position, property, Convert. ToInt32 ( range. min) , Convert. ToInt32 ( range. max) , label) ; else EditorGUI. LabelField ( position, label. text, "将 Range 与 float 或 int 一起使用。" ) ; }
}