找回密码
 立即注册
查看: 1875|回复: 10

[简易教程] 自定义属性面板Inspector详解

[复制链接]
发表于 2018-8-28 18:02 | 显示全部楼层 |阅读模式
通常情况是不需要扩展属性面板的,也就是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    }}
自定义属性详细介绍
  • 绘制原有属性
public override void OnInspectorGUI(){    // 绘制全部原有属性    base.DrawDefaultInspector();    // 后面可以扩展自己功能}
  • 自定义绘制
有两个重要的内置对象,target和serializedObject。target代表的是CustomEditorTest本身,而serializedObject代表的是当前Inspector的可绘制对象。
  public override void OnInspectorGUI()  {      // 更新显示      this.serializedObject.Update();             // 自定义绘制            // 应用属性修改      this.serializedObject.ApplyModifiedProperties();  }
  • 绘制已经有的属性
有两个接口用来查找已有的属性,FindProperty和FindPropertyRelative。FindProperty用来查找当前属性名对应的属性对象,FindPropertyRelative查找相对于属性对象的属性。
// 显示intValue属性EditorGUILayout.PropertyField(this.serializedObject.FindProperty("intValue"));// 显示boolValue并替换属性标签为GUIContentEditorGUILayout.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表示属性控件不可用,或者处在不可见的状态。





  • 绘制数组属性
// 查找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。





  • 绘制默认数组和对象
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 绘制折叠动画
// 每个动画都需要一个AnimBoolprivate 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的功能。





  • 绘制水平布局
// 水平布局,并使用box皮肤EditorGUILayout.BeginHorizontal(GUI.skin.box);// 使用了GUILayout去覆盖自动布局的设置EditorGUILayout.LabelField("This is BeginHorizontal", GUILayout.MaxWidth(150.0f));EditorGUILayout.DelayedDoubleField(11.1f);EditorGUILayout.DelayedTextField("DelayedTextField");EditorGUILayout.DropdownButton(GUIContent.none, FocusType.Passive);EditorGUILayout.EndHorizontal();EditorGUILayout.Separator();




  • 绘制垂直布局
EditorGUILayout.BeginVertical(GUI.skin.box);// 依然可以使用GUILayout来显示控件GUILayout.Box("This is BeginVertical");EditorGUILayout.ColorField("ColorField", Color.yellow);EditorGUILayout.CurveField("CurveField", new AnimationCurve(), GUILayout.MaxWidth(400.0f));EditorGUILayout.HelpBox("HelpBox", MessageType.Info);EditorGUILayout.EnumFlagsField("EnumFlagsField", this.types);EditorGUILayout.EnumPopup("EnumPopup", this.types);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[] {"mask1", "mask2", "mask3"});this.selectOption = EditorGUILayout.Popup("Popup", (int) this.selectOption, new string[] {"s1", "s2", "s3"});EditorGUILayout.EndVertical();EditorGUILayout.Separator();




  • 绘制滚动区域
// 超出内容会出现滚动条this.scrollPos   = EditorGUILayout.BeginScrollView(this.scrollPos, GUI.skin.box);GUILayout.Box("this is BeginScrollView");EditorGUILayout.TextArea("this is TextArea");EditorGUILayout.RectField("RectField", new Rect());this.toggle      = EditorGUILayout.Toggle("Toggle", this.toggle);// 在toggleGroup之间的会被整体设置可用性this.toggleGroup = EditorGUILayout.BeginToggleGroup("BeginToggleGroup", this.toggleGroup);GUILayout.Button("Btn1");GUILayout.Button("Btn2");GUILayout.Button("Btn3");EditorGUILayout.EndToggleGroup();EditorGUILayout.EndScrollView();




总结
  • PropertyField方法是用来显示已有属性控件的,第二个参数为true则绘制所有子元素。
  • Delayed开头的Field方法,是延迟控件。回车确定后,数值才会返回。
  • 其它Field方法是用来绘制自定义控件的。
  • Begin - End 是区域绘制控件,在之间的绘制会被整体控制。
  • 可以混合使用GUI和GUILayout以及EditorGUI进行绘制。
  • GUIContent 提供了重写控件名字和添加提示的机会。
  • GUILayoutOption 是覆盖自动布局的设置,属性来自于GUILayout类。



作者:scottcgi
链接:https://www.jianshu.com/p/497fcbad2ad0
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

发表于 2018-9-17 10:43 | 显示全部楼层
楼主是超人
发表于 2018-9-17 10:52 | 显示全部楼层
难得一见的好帖
发表于 2018-9-17 10:39 | 显示全部楼层
说的非常好
发表于 2018-9-17 10:25 | 显示全部楼层
不错不错
发表于 2018-9-17 11:16 | 显示全部楼层
LZ真是人才
发表于 2019-7-2 08:01 | 显示全部楼层
好帖就是要顶
发表于 2019-7-2 08:05 | 显示全部楼层
真心顶
发表于 2019-7-2 08:07 | 显示全部楼层
很好哦
发表于 2019-7-2 08:18 | 显示全部楼层
不错不错
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-5-22 23:57 , Processed in 0.099233 second(s), 26 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表