找回密码
 立即注册
查看: 537|回复: 0

Unity 编辑器扩展二 Editor 自定义Inspector面板

[复制链接]
发表于 2021-12-9 18:26 | 显示全部楼层 |阅读模式
OnInspectorGUI()是Unity的Editor类里的相关函数,通过对该方法的重写,可以自定义对Inspector面板的绘制。


image.png

//Test1.csusing System.Collections;using System.Collections.Generic;using UnityEngine;using UnityEngine.UI;public class Test1 : MonoBehaviour{    public Text Text1;    public bool myBool;    public string myString;}//Test1Editor.csusing UnityEditor;using UnityEngine;[CustomEditor(typeof(Test1))]public class Test1Editor : Editor{    public override void OnInspectorGUI()    {        Test1 test = (Test1)target;        test.myBool = EditorGUILayout.Toggle("是否选中", test.myBool);        test.myString = EditorGUILayout.TextField("输入文本", test.myString);    }}
这里要先创建Test1脚本,再创建Test1Editor,否则引用会报错。


看一下前后对比图

如图对比,重写了OnInspectorGUI之后,Inspector面板发生变化。因为没有处理Text1,重写之后已经无法设置。

以下参考
【Unity 编辑器】扩展总结三:自定义Inspector面板
Unity Editor 基础篇(二):自定义 Inspector 面板
Unity检视面板重构(OnInspectorGUI重写)
unity编辑器扩展#1 自定义窗口、面板、和属性
一、两种方式


创建目标类,挂载在场景对象中
using UnityEngine;public enum Course{    Chinese,    Mathematics,     English }public class InspectorExample : MonoBehaviour{    public int intValue;    public float floatValue;    public string stringValue;    public bool boolValue;    public Vector3  vector3Value;     public Course enumValue = Course.Chinese;    public Color colorValue = Color.white;    public Texture textureValue;}1.绘制方式一

using UnityEngine;using UnityEditor;[CustomEditor(typeof(InspectorExample))]public class InspectorExampleEditor : Editor{    //target指该编辑器类绘制的目标类,需要将它强转为目标类    private InspectorExample _target { get { return target as InspectorExample; } }    //GUI重新绘制    public override void OnInspectorGUI()    {        //EditorGUILayout.LabelField("IntValue",_target.intValue.ToString(),EditorStyles.boldLabel);        //_target.intValue = EditorGUILayout.IntSlider(new GUIContent("Slider"),_target.intValue, 0, 10);        //_target.floatValue = EditorGUILayout.Slider(new GUIContent("FloatValue"), _target.floatValue, 0, 10);        _target.intValue = EditorGUILayout.IntField("IntValue", _target.intValue);        _target.floatValue = EditorGUILayout.FloatField("FloatValue", _target.floatValue);        _target.stringValue = EditorGUILayout.TextField("StringValue", _target.stringValue);        _target.boolValue = EditorGUILayout.Toggle("BoolValue", _target.boolValue);        _target.vector3Value = EditorGUILayout.Vector3Field("Vector3Value", _target.vector3Value);        _target.enumValue = (Course)EditorGUILayout.EnumPopup("EnumValue", (Course)_target.enumValue);        _target.colorValue = EditorGUILayout.ColorField(new GUIContent("ColorValue"), _target.colorValue);        _target.textureValue = (Texture)EditorGUILayout.ObjectField(        "TextureValue", _target.textureValue, typeof(Texture), true);    }}2.绘制方式二

using UnityEditor;[CustomEditor(typeof(InspectorExample))]public class InspectorExampleEditor : Editor{    //定义序列化属性    private SerializedProperty intValue;    private SerializedProperty floatValue;    private SerializedProperty stringValue;    private SerializedProperty boolValue;    private SerializedProperty vector3Value;    private SerializedProperty enumValue;    private SerializedProperty colorValue;    private SerializedProperty textureValue;    private void OnEnable()    {        //通过名字查找被序列化属性。        intValue = serializedObject.FindProperty("intValue");        floatValue = serializedObject.FindProperty("floatValue");        stringValue = serializedObject.FindProperty("stringValue");        boolValue = serializedObject.FindProperty("boolValue");        vector3Value = serializedObject.FindProperty("vector3Value");        enumValue = serializedObject.FindProperty("enumValue");        colorValue = serializedObject.FindProperty("colorValue");        textureValue = serializedObject.FindProperty("textureValue");    }    public override void OnInspectorGUI()    {        //表示更新序列化物体        serializedObject.Update();        EditorGUILayout.PropertyField(intValue);        EditorGUILayout.PropertyField(floatValue);        EditorGUILayout.PropertyField(stringValue);        EditorGUILayout.PropertyField(boolValue);        EditorGUILayout.PropertyField(vector3Value);        EditorGUILayout.PropertyField(enumValue);        EditorGUILayout.PropertyField(colorValue);        EditorGUILayout.PropertyField(textureValue);        //应用修改的属性值,不加的话,Inspector面板的值修改不了        serializedObject.ApplyModifiedProperties();    }}
P.S. 第二种绘制方式相较于第一种,显示的效果是差不多的。虽然脚本内容多了一点,但是方式比较简单。不用根据每个变量的数据类型选择相对应的属性API绘制。
3.使用方式二改造之前的Test1Editor

using UnityEditor;using UnityEngine;[CustomEditor(typeof(Test1))]public class Test1Editor : Editor{    //定义序列化属性    private SerializedProperty Text1;    private SerializedProperty myBool;    private SerializedProperty myString;    private void OnEnable()    {        //通过名字查找被序列化属性。        Text1 = serializedObject.FindProperty("Text1");        myBool = serializedObject.FindProperty("myBool");        myString = serializedObject.FindProperty("myString");        Debug.Log("test 1 editor enable");    }    public override void OnInspectorGUI()    {        //Test1 test = (Test1)target;        //test.myBool = EditorGUILayout.Toggle("是否选中", test.myBool);        //test.myString = EditorGUILayout.TextField("输入文本", test.myString);        //表示更新序列化物体        serializedObject.Update();        EditorGUILayout.PropertyField(Text1);        //EditorGUILayout.PropertyField(myBool);        EditorGUILayout.PropertyField(myBool, new GUIContent("是否选中"));        EditorGUILayout.PropertyField(myString);        //应用修改的属性值,不加的话,Inspector面板的值修改不了        serializedObject.ApplyModifiedProperties();    }}
这里PropertyField如果需要修改显示属性,可以参考Unity属性窗口编辑器,改为EditorGUILayout.PropertyField(myBool, new GUIContent("是否选中"));
4.布局

        serializedObject.Update();        EditorGUILayout.BeginHorizontal("box");        EditorGUILayout.PropertyField(Text1);        //EditorGUILayout.PropertyField(myBool);        EditorGUILayout.PropertyField(myBool, new GUIContent("是否选中"));        EditorGUILayout.EndHorizontal();        EditorGUILayout.PropertyField(myString);

image.png

水平和垂直布局,注意这是一个方法对,Begin和End不能少
EditorGUILayout.BeginVertical("box"); //TODO EditorGUILayout.EndVertical(); EditorGUILayout.BeginHorizontal("box"); //TODO EditorGUILayout.EndHorizontal();二、数组或list集合的显示方式


参考【Unity 编辑器】扩展总结七:数组或list集合的显示方式
using System.Collections.Generic;using UnityEngine;public class InspectorExample : MonoBehaviour{    //序列化    [SerializeField]     public int[] intArray;    [SerializeField]    public List<string> stringList;}using UnityEditor;[CustomEditor(typeof(InspectorExample))]public class InspectorExampleEditor : Editor{    private SerializedProperty intArray;    private SerializedProperty stringList;    private void OnEnable()    {        intArray = serializedObject.FindProperty("intArray");        stringList = serializedObject.FindProperty("stringList");    }    public override void OnInspectorGUI()    {        serializedObject.Update();        EditorGUILayout.PropertyField(intArray,true);        EditorGUILayout.PropertyField(stringList, true);        serializedObject.ApplyModifiedProperties();    }}三、ReorderableList实现可排序列表


参考【Unity 编辑器】扩展总结七:数组或list集合的显示方式,原文中还有拓展:ReorderableList添加下拉菜单,这里不再转载。
using System.Collections.Generic;using UnityEngine;public class TargetExample : MonoBehaviour{   [SerializeField]   public List<string> stringArray;}using UnityEngine;using UnityEditor;using UnityEditorInternal;[CustomEditor(typeof(TargetExample))]public class TargetExampleEditor : Editor{   private ReorderableList _stringArray;   private void OnEnable()   {       _stringArray = new ReorderableList(serializedObject, serializedObject.FindProperty("stringArray")           , true, true, true, true);       //自定义列表名称       _stringArray.drawHeaderCallback = (Rect rect) =>       {           GUI.Label(rect, "StringArray");       };       //自定义绘制列表元素       _stringArray.drawElementCallback = (Rect rect,int index,bool selected,bool focused) =>       {           //根据index获取对应元素           SerializedProperty item = _stringArray.serializedProperty.GetArrayElementAtIndex(index);           rect.height = EditorGUIUtility.singleLineHeight;           rect.y += 2;           EditorGUI.PropertyField(rect, item, new GUIContent("Element "+index));       };       //当添加新元素时的回调函数,自定义新元素的值       _stringArray.onAddCallback = (ReorderableList list) =>       {           if (list.serializedProperty != null)           {               list.serializedProperty.arraySize++;               list.index = list.serializedProperty.arraySize - 1;               SerializedProperty item = list.serializedProperty.GetArrayElementAtIndex(list.index);               item.stringValue = "Default Value";           }           else           {               ReorderableList.defaultBehaviours.DoAddButton(list);           }       };       //当删除元素时候的回调函数,实现删除元素时,有提示框跳出       _stringArray.onRemoveCallback = (ReorderableList list) =>       {           if (EditorUtility.DisplayDialog("Warnning","Do you want to remove this element?","Remove","Cancel"))           {               ReorderableList.defaultBehaviours.DoRemoveButton(list);           }       };   }   public override void OnInspectorGUI()   {       serializedObject.Update();       //自动布局绘制列表       _stringArray.DoLayoutList();       serializedObject.ApplyModifiedProperties();   }}

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2024-11-16 06:43 , Processed in 0.091842 second(s), 26 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

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