Unity-实现自定义Inspector

一、Unity编辑器扩展,对自己写的组件编写编辑器样式

以下图为例,实现如图的样式。

二、创建Monobehaviour脚本

首先在非Editor文件夹中创建脚本,添加一些常见类型的字段和可序列化的类型。

public enum Course
{
    Chinese,
    Mathematics,
    English
}
public class TestInspector : 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;
    public selfData selfData;
    public List<int> intList=new List<int>();
}
[System.Serializable]
public class selfData
{
    public string id;
    public string type;
    public string code;
    public string tag;
    [SceneDropdown]
    public string scene;
    [SceneDropdown(new string []{"1","2","3"})]
    public string customScene;
}
public class SceneDropdownAttribute : PropertyAttribute //可以为添加该特性的字段编写特殊样式
{
    public string[] items;
    public SceneDropdownAttribute() {  }

    public SceneDropdownAttribute(string[] items) { this.items = items; }
}

三、在Editor文件夹中编写对应的Editor代码

using UnityEngine;
using UnityEditor;
using DataPaddyBoot.Runtime.Pool;
using System.Linq;

[CanEditMultipleObjects]
[CustomEditor(typeof(TestInspector))] //将要重绘的target类传给Editor类
public class TestInspectorGUI : Editor
{
    //#region 法一
    ////强转为目标类
    //private MyInspector _target { get { return target as MyInspector; } }

    ////InspectorGUI重绘
    //public override void OnInspectorGUI()
    //{
    //    EditorGUILayout.BeginVertical();

    //    _target.intValue = EditorGUILayout.IntField("ontValue", _target.intValue);                  //int --> IntField
    //    _target.floatValue = EditorGUILayout.FloatField("floatValue", _target.floatValue);          //float --> FloatField
    //    _target.stringValue = EditorGUILayout.TextField("stringValue", _target.stringValue);        //string --> TextField
    //    _target.boolValue = EditorGUILayout.Toggle("boolValue", _target.boolValue);                 //bool --> Toggle
    //    _target.vector3Value = EditorGUILayout.Vector3Field("vector3Value", _target.vector3Value);  //vector3 --> Vector3Field
    //    _target.enumValue = (Course)EditorGUILayout.EnumPopup("enumValue", (Course)_target.enumValue); //enum --> EnumPopup 需要强转
    //    _target.colorValue = EditorGUILayout.ColorField(new GUIContent("colorValue"), _target.colorValue);//color --> ColorField
    //    _target.textureValue = (Texture)EditorGUILayout.ObjectField("textureValue", _target.textureValue, typeof(Texture), true); //texture -->

    //    EditorGUILayout.EndVertical();
    //}
    //#endregion

    #region 法二  此脚本效果和Base.OnInspectorGUI即默认效果一样
    //自定义序列化属性
    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 SerializedProperty selfData;

    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");
        selfData = serializedObject.FindProperty("selfData");
    }

    public override void OnInspectorGUI()
    {
        //表示更新序列化物体
        serializedObject.Update();
        EditorGUILayout.PropertyField(intValue);
        EditorGUILayout.PropertyField(floatValue);
        EditorGUILayout.PropertyField(stringValue);
        EditorGUILayout.PropertyField(boolValue, new GUIContent("布尔"), true);//修改显示名称
        if(boolValue.boolValue)
        {
            EditorGUI.indentLevel = 1;//设置缩进等级
            EditorGUILayout.PropertyField(vector3Value);
            EditorGUI.indentLevel = 0;
        }
        EditorGUILayout.PropertyField(enumValue);
        EditorGUILayout.PropertyField(colorValue);
        EditorGUILayout.PropertyField(textureValue);
        EditorGUILayout.PropertyField(selfData);
        //应用修改的属性值,不加的话,Inspector面板修改不了
        serializedObject.ApplyModifiedProperties();
    }
    #endregion
}

[CustomPropertyDrawer(typeof(selfData))]
public class selfDataDrawer:PropertyDrawer
{
    bool exp = true;

    public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
    {
        return 0;
    }
    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    {
        exp = EditorGUILayout.Foldout(exp, "设置");
        if(exp)
        {
            EditorGUILayout.LabelField("对象数据");
            SerializedProperty idPro = property.FindPropertyRelative("id");
            SerializedProperty typePro = property.FindPropertyRelative("type");
            SerializedProperty codePro = property.FindPropertyRelative("code");
            SerializedProperty tagPro = property.FindPropertyRelative("tag");
            SerializedProperty scPro = property.FindPropertyRelative("scene");
            SerializedProperty cscPro = property.FindPropertyRelative("customScene");
            EditorGUILayout.BeginVertical("Box");
            EditorGUILayout.PropertyField(idPro);
            EditorGUILayout.PropertyField(typePro);
            EditorGUILayout.PropertyField(codePro);
            EditorGUILayout.PropertyField(tagPro);
            EditorGUILayout.PropertyField(scPro);
            EditorGUILayout.PropertyField(cscPro);
            EditorGUILayout.EndVertical();
        }
    }
}

[CustomPropertyDrawer(typeof(SceneDropdownAttribute),false)]
public class SceneDropdownDrawer:PropertyDrawer
{
    public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
    {
        return 0;
    }
    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    {
        SceneDropdownAttribute tar = attribute as SceneDropdownAttribute;
        if(tar.items==null)
        {
            //其他来源的下拉数据列表
            var scenes = DataPaddyBootScenePoolManager.Instance.dataPaddySceneDataList.Select(scene =>
            {
                var sceneName = scene.sceneName;
                return sceneName;
            }).ToList();
            scenes.Insert(0, "无");

            string curValue = property.stringValue;
            int curSel = scenes.FindIndex(vs => vs.Equals(curValue));
            if (curSel < 0) { curSel = 0;property.stringValue = scenes[0]; }
            EditorGUI.BeginChangeCheck();
            int newIndex = EditorGUILayout.Popup(curSel, scenes.ToArray());
            if (EditorGUI.EndChangeCheck())
            {
                property.stringValue = scenes[newIndex];
            }
        }
        else
        {
            //从特性中输入下拉的数据列表
            var scenes = tar.items;
            string curValue = property.stringValue;
            int curSel = ArrayUtility.IndexOf(scenes, curValue);
            EditorGUI.BeginChangeCheck();
            int newIndex = EditorGUILayout.Popup(curSel, scenes.ToArray());
            if (EditorGUI.EndChangeCheck())
            {
                property.stringValue = scenes[newIndex];
            }
        }
    }
}

Unity Basic Customizations

1、unity内置的特性如 Header、Range 、Space 、Tooltip 。

2、ContextMenu Attribute,只能在方法上添加,作用是右键菜单添加一个按钮。

3、Customiz the Inspector,自定义Inspector。

4、MenuItem,增加一个菜单栏按钮。可以为这个按钮设置快捷键。

5、CustomWindow,自定义编辑器窗口。需要通过MenuItem打开窗口。

6、Gizoms 和GizmosSelected,绘制Gizoms。

7、UnityEditor.EditorUtility.SetDirty();

8、UnityEditor.PrefabUtility.InstantiatePrefab();

9、js URL.createObjectURL()

10、xNode 一个绘制流程图的框架。https://github.com/ma1238906/xNode-queueGraph

点赞

发表回复

昵称和uid可以选填一个,填邮箱必填(留言回复后将会发邮件给你)
tips:输入uid可以快速获得你的昵称和头像