Unity 编辑器扩展二 Editor 自定义Inspector面板
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;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 Vector3vector3Value; public Course enumValue = Course.Chinese; public Color colorValue = Color.white; public Texture textureValue;}1.绘制方式一
using UnityEngine;using UnityEditor;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;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;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{ //序列化 public int[] intArray; public List<string> stringList;}using UnityEditor;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{ public List<string> stringArray;}using UnityEngine;using UnityEditor;using UnityEditorInternal;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(); }}
页:
[1]