自定义UI界面inspector面板(Editor)以及自定义参数在inspector面板内显示效果(PropertyDrawer)

平时我们在搭建一个界面后都会给这个界面添加一个界面脚本,一般情况下都是普通的MonoBehaviour的。

此时脚本内定义的参数可以通过public或者特性[SerializeField]显示在inspector面板内。

但有时我们可能希望在面板上加一个按钮,然后能在编辑器模式下点击这个按钮就会执行脚本内的某个方法,此时就需要自定义这个面板。

代码如下示例:

普通界面脚本:

该脚本内有两个列表:templateDatas存储了实例的数据,templates存储了创建的实例对象

以及一些初始化的方法

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

/// <summary>
/// 东/西部概况界面
/// </summary>
public class GeneralSituation : MonoBehaviour
{
    /// <summary>
    /// 示例物体
    /// </summary>
    private Template template;
    /// <summary>
    /// 显示区域
    /// </summary>
    private Transform content;
    
    /// <summary>
    /// 实例列表
    /// </summary>
    private List<Template> templates = new List<Template>();

    /// <summary>
    /// 实例数据列表
    /// </summary>
    [SerializeField]
    private List<TemplateData> templateDatas = new List<TemplateData>();

    /// <summary>
    /// 初始化实例
    /// </summary>
    public void InitTemplates()
    {
        
    }
    
    /// <summary>
    /// 初始化
    /// </summary>
    public void Init()
    {
        if(template == null)
        {
            template = this.transform.Find("Template").GetComponent<Template>();
        }
        if(content == null)
        {
            content = this.transform.Find("显示列表/Viewport/Content");
        }
    }
}

Template与TemplateData数据脚本:

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

/// <summary>
/// 概况界面实例
/// </summary>
public class Template : MonoBehaviour
{
    /// <summary>
    /// 标签
    /// </summary>
    [SerializeField]
    private Text title;
    /// <summary>
    /// 值
    /// </summary>
    [SerializeField]
    private Text value;
    /// <summary>
    /// 字体颜色
    /// </summary>
    [SerializeField]
    private Color color;

    /// <summary>
    /// 设置标签内容
    /// </summary>
    /// <param name="title"></param>
    public void SetTitle(string title)
    {
        this.title.text = title;
        this.title.color = color;
    }

    /// <summary>
    /// 设置值
    /// </summary>
    /// <param name="value"></param>
    public void SetValue(string value)
    {
        this.value.text = value;
        this.value.color = color;
    }

    /// <summary>
    /// 设置颜色
    /// </summary>
    /// <param name="color"></param>
    public void SetColor(Color color)
    {
        this.color = color;
        this.title.color = color;
        this.value.color = color;
    }

    /// <summary>
    /// 获取标签内容
    /// </summary>
    /// <returns></returns>
    public string GetTitle()
    {
        return this.title.text;
    }
}

/// <summary>
/// 实例数据
/// </summary>
[Serializable]
public class TemplateData
{
    [SerializeField]
    public string title;
    [SerializeField]
    public string value;
    [SerializeField]
    public Color color;

    public TemplateData(string title, string value, Color color)
    {
        this.title = title;
        this.value = value;
        this.color = color;
    }
}

界面编辑器脚本:

该脚本继承Editor,加上特性[CustomEditor(typeof(具体界面类))],然后实现OnInspectorGUI()方法即可自定义inspector显示面板,效果图如下

using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;

/// <summary>
/// 东/西部概况界面编辑器
/// </summary>
[CustomEditor(typeof(GeneralSituation))]
public class GeneralSituationEditor : Editor
{
    GeneralSituation ui;
    GUILayoutOption[] options = new GUILayoutOption[] { GUILayout.Width(100f) };
    public override void OnInspectorGUI()
    {
        base.OnInspectorGUI();
        ui = (GeneralSituation)this.target;

        ui.Init();

        GUILayout.BeginVertical();
//若设置了参数的显示效果,此处可注释掉
        for (int i = 0; i < ui.templateDatas.Count; i++)
        {
            GUILayout.BeginHorizontal();
            EditorGUILayout.LabelField("标题:", new GUILayoutOption[] { GUILayout.Width(30f) });
            ui.templateDatas[i].title = EditorGUILayout.TextField(ui.templateDatas[i].title, options);
            EditorGUILayout.LabelField("值:", new GUILayoutOption[] { GUILayout.Width(30f) });
            ui.templateDatas[i].value = EditorGUILayout.TextField(ui.templateDatas[i].value, options);
            EditorGUILayout.LabelField("颜色:", new GUILayoutOption[] { GUILayout.Width(30f) });
            ui.templateDatas[i].color = EditorGUILayout.ColorField(ui.templateDatas[i].color, options);

            if (GUILayout.Button("-", new GUILayoutOption[] { GUILayout.Width(20f) }))
            {
                ui.templateDatas.Remove(ui.templateDatas[i]);
            }
            GUILayout.EndHorizontal();
        }

        if (GUILayout.Button("+", new GUILayoutOption[] { GUILayout.Width(20f) }))
        {
            ui.templateDatas.Add(new TemplateData("", "", Color.white));
        }

//可注释
        if (GUILayout.Button("确定", new GUILayoutOption[] { GUILayout.Width(100f) }))
        {
            ui.InitTemplates();
        }

        GUILayout.EndVertical();
    }
}

效果图:

 若要修改参数在inspector面板显示,需要新建一个脚本继承PropertyDrawer,然后添加特性[CustomPropertyDrawer(typeof(参数类名))],然后实现OnGUI()方法,示例如下

TemplateDataDrawer:

using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;

/// <summary>
/// 实例数据编辑器
/// </summary>
[CustomPropertyDrawer(typeof(TemplateData))]
public class TemplateDataDrawer : PropertyDrawer
{
    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    {
        EditorGUI.BeginProperty(position, label, property);
        //FocusType.Passive 使用Tab键切换时不会被选中,FocusType.Keyboard 使用Tab键切换时会被选中
        position = EditorGUI.PrefixLabel(position, GUIUtility.GetControlID(FocusType.Passive), label);
        //不让indentLevel层级影响到同一行的绘制,因为PropertyDrawer在很多地方都有可能被用到,可能出现嵌套使用
        var indent = EditorGUI.indentLevel;
        EditorGUI.indentLevel = 0;
        //定义各数据显示区域位置与大小
        var titleRect = new Rect(position.x, position.y,100, position.height);
        var valueRect = new Rect(position.x + 105, position.y, 50, position.height);
        var colorRect = new Rect(position.x + 160, position.y, 50, position.height);
        //设置参数对应位置与大小
        EditorGUI.PropertyField(titleRect, property.FindPropertyRelative("title"), GUIContent.none);
        EditorGUI.PropertyField(valueRect, property.FindPropertyRelative("value"), GUIContent.none);
        EditorGUI.PropertyField(colorRect, property.FindPropertyRelative("color"), GUIContent.none);
        EditorGUI.indentLevel = indent;
        EditorGUI.EndProperty();
    }
}

效果如图:

两者结合即可实现inspector面板的自定义效果 ,当然也可以分开使用

猜你喜欢

转载自blog.csdn.net/qq_42720695/article/details/126282838