「Unity3D」(10)⾃定义属性⾯板Inspector详解
通常情况是不需要扩展属性⾯板的,也就是Inspector,但如果需要开发定制的⼯具和插件,那么就需要扩展属性⾯板来完成需求。本⽂会对⾃定义扩展Inspector进⾏全⾯的介绍。
⼯具类和概念的介绍
⾃定义Inspector有两个层⾯,第⼀个是扩展已有属性的功能,第⼆个是按照意图增加新的⾯板功能。扩展已有的功能,包括替换显⽰⽂字,动态控制可见性,增加动画,错误提⽰,数据的校验和限制等等。增加新的功能就是按照需求定制更为复杂的功能。
Unity的内置⼯具类提供了必要的实现基础,主要有EditorGUILayout和EditorGUI两⼤类。两者有重叠的部分,也有特有的部分。总体上来说,EditorGUILayout是带有⾃动布局的,EditorGUI需要传⼊Rect来对控件进⾏定位。另外,这两者和GUILayout与GUI概念⾮常类似,只不过GUI的主要绘制是在场景中(运⾏时,游戏中可见),EditorGUI上在Inspector中(仅在编辑器中)。
⾃定义流程
⼀共分为三步:
第⼀步,继承Editor⽗类。
第⼆步,添加[CustomEditor(typeof(MonoBehaviour))]注解,告诉编辑器这个类是扩展哪个组件的Inspector。
第三步,覆写OnInspectorGUI⽅法,实现⾃定义的扩展。
public class CustomEditorTest : MonoBehaviour
{
[Space(10)]
public int    intValue;
public bool    boolValue;
public Vector2 v2;
public float[] floatArray =new float[]{1.0f,2.0f,3.0f};
}
[CanEditMultipleObjects,CustomEditor(typeof(CustomEditorTest))]
public class CustomEditorTestEditor : Editor
{
public override void OnInspectorGUI()
{
// ⾃定义绘制Inspector
}
}
⾃定义属性详细介绍
1. 绘制原有属性
public override void OnInspectorGUI()
{
/
/ 绘制全部原有属性
base.DrawDefaultInspector()
// 后⾯可以扩展⾃⼰功能
}
2. ⾃定义绘制
有两个重要的内置对象,target和serializedObject。target代表的是CustomEditorTest本⾝,⽽serializedObject代表的是当前Inspector的可绘制对象。
public override void OnInspectorGUI()
{
// 更新显⽰
this.serializedObject.Update();
// ⾃定义绘制
// 应⽤属性修改
this.serializedObject.ApplyModifiedProperties();
}
3. 绘制已经有的属性
有两个接⼝⽤来查已有的属性,FindProperty和FindPropertyRelative。FindProperty⽤来查当前属性名对应的属性对
象,FindPropertyRelative查相对于属性对象的属性。
// 显⽰intValue属性
EditorGUILayout.PropertyField(this.serializedObject.FindProperty("intValue"));
// 显⽰boolValue并替换属性标签为GUIContent
EditorGUILayout.PropertyField(this.serializedObject.FindProperty("boolValue"),this.boolValueContent);
var v2Property =this.serializedObject.FindProperty("v2");
// 现实v2属性
EditorGUILayout.PropertyField(v2Property);
// 设置v2属性的x属性值
v2Property.FindPropertyRelative("x").floatValue =999.0f;
// 分隔符
EditorGUILayout.Separator();
EditorGUILayout.PropertyField能够在Inspector上绘制属性控件,如果返回false表⽰属性控件不可⽤,或者处在不可见的状态。
4. 绘制数组属性
// 查floatArray属性
var elements =this.serializedObject.FindProperty("floatArray");
// 属性元素可见,控件展开状态
if(EditorGUILayout.PropertyField(elements))
{
// 缩进⼀级
EditorGUI.indentLevel++;
// 设置元素个数
elements.arraySize = EditorGUILayout.DelayedIntField("Size", elements.arraySize);
// 绘制元素
for(int i =0, size = elements.arraySize; i < size; i++)
{
// 检索属性数组元素
var element = elements.GetArrayElementAtIndex(i);
EditorGUILayout.PropertyField(element);
}
// 重置缩进
EditorGUI.indentLevel--;
}
// 空格
EditorGUILayout.Space();
对elements.arraySize赋值就会⾃动设置数组容量。DelayedIntField在回车的时候,控件设置的数值才会返回到arraySize。
5. 绘制默认数组和对象
public CustomData  data;
public CustomData[] datas;
[System.Serializable]
public class CustomData
{
public int a;
public int b;
public int c;
}
// 第⼆个参数为true,则会默认绘制所有⼦元素
EditorGUILayout.PropertyField(this.serializedObject.FindProperty("data"),true);
EditorGUILayout.PropertyField(this.serializedObject.FindProperty("datas"),true);
6. 绘制折叠动画
// 每个动画都需要⼀个AnimBool
private AnimBool fadeGroup;
private void OnEnable()
{
this.fadeGroup =new AnimBool(true);
// 注册动画监听
this.fadeGroup.valueChanged.AddListener(this.Repaint);
}
private void OnDisable()
{
// 移除动画监听
this.fadeGroup.valueChanged.RemoveListener(this.Repaint);
}
// target控制动画开始播放
this.fadeGroup.target = EditorGUILayout.Foldout(this.fadeGroup.target,"BeginFadeGroup",true); // 系统使⽤tween渐变faded数值
if(EditorGUILayout.BeginFadeGroup(this.fadeGroup.faded))
{
EditorGUILayout.BoundsField("BoundsField",new Bounds());
EditorGUILayout.BoundsIntField("BoundsIntField",new BoundsInt());
}
// begin - end 之间元素会进⾏动画
EditorGUILayout.EndFadeGroup();
// ⼜⼀种风格的空格
GUILayout.Space(10);
Editor中依然可以使⽤GUILayout的功能。
unity3d animation
7. 绘制⽔平布局
// ⽔平布局,并使⽤box⽪肤
EditorGUILayout.BeginHorizontal(GUI.skin.box);
// 使⽤了GUILayout去覆盖⾃动布局的设置
EditorGUILayout.LabelField("This is BeginHorizontal", GUILayout.MaxWidth(150.0f)); EditorGUILayout.DelayedDoubleField(11.1f);
EditorGUILayout.DelayedTextField("DelayedTextField");
EditorGUILayout., FocusType.Passive); EditorGUILayout.EndHorizontal();
EditorGUILayout.Separator();
8. 绘制垂直布局
EditorGUILayout.BeginVertical(GUI.skin.box);
// 依然可以使⽤GUILayout来显⽰控件
GUILayout.Box("This is BeginVertical");
EditorGUILayout.ColorField("ColorField", llow);
EditorGUILayout.CurveField("CurveField",new AnimationCurve(), GUILayout.MaxWidth(400.0f));
EditorGUILayout.HelpBox("HelpBox", MessageType.Info);
EditorGUILayout.EnumFlagsField("EnumFlagsField",pes);
EditorGUILayout.EnumPopup("EnumPopup",pes);
this.selectOption = EditorGUILayout.IntPopup("IntPopup",(int)this.selectOption,new string[]{"0","1","2"},new int[]{0,1,2}); this.selectOption = EditorGUILayout.IntSlider("IntSlider",(int)this.selectOption,0,2);
this.selectOption = EditorGUILayout.MaskField("MaskField",(int)this.selectOption,new string[]{"mask
1","mask2","mask3"}); this.selectOption = EditorGUILayout.Popup("Popup",(int)this.selectOption,new string[]{"s1","s2","s3"});
EditorGUILayout.EndVertical();
EditorGUILayout.Separator();
9. 绘制滚动区域
// 超出内容会出现滚动条
this.scrollPos  = EditorGUILayout.BeginScrollView(this.scrollPos, GUI.skin.box);
GUILayout.Box("this is BeginScrollView");
EditorGUILayout.TextArea("this is TextArea");
EditorGUILayout.RectField("RectField",new Rect());
// 在toggleGroup之间的会被整体设置可⽤性
GUILayout.Button("Btn1");
GUILayout.Button("Btn2");
GUILayout.Button("Btn3");
EditorGUILayout.EndToggleGroup();
EditorGUILayout.EndScrollView();
总结

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。