Unity编辑器教程用法——自定义Inspector 面板编辑器Chinar

37 篇文章 5 订阅

Chinar blog www.chinar.xin

自定义Inspector 面板编辑器


本文提供全流程,中文翻译。

Chinar 的初衷是将一种简单的生活方式带给世人

使有限时间 具备无限可能

Chinar ―― 心分享、心创新!

助力快速了解编辑器扩展如何使我们高效的工作

为初学者节省宝贵的时间,避免采坑!

Chinar 教程效果:
自定义Inspector 面板编辑器



全文高清图片,点击即可放大观看 (很多人竟然不知道)


1

Intro —— 介绍


有些插件会写大量的编辑器类,来便于开发者对插件属性的调整。

这其中就有很多对 Inspector面板重新绘制,使开发者可以可视化的调整相应参数
举个例子
在这里插入图片描述


2

Custom Inspector Editor ―― 自定义检视面板编辑器


众所周知,一个继承 MonBehaviour 类的脚本

我们可以通过 Public 来使其中变量显示在Inspector面板,以便于我们对其参数值进行调整

1 —— 首先,我们自定义一个要被扩展的目标脚本

需继承 MonBehaviour

 public class ChinarInspector: MonoBehaviour
{
    public int A;   //字段A
    public string B;//字段B
}

举个例子 挂载脚本后,Inspector 所示:
在这里插入图片描述

2 —— 需要一个与之对应的编辑器脚本,对目标脚本在 Inspector 面板上的显示,进行重写

该脚本需要放在 Editor 文件夹中,并且要继承 Editor

using UnityEditor;


[CustomEditor(typeof(ChinarInspector))] //特性:自定义编辑类 ChinarInspector
public class ChinarEditor : Editor      //需要继承 Editor
{
    private ChinarInspector chinarInspector; // 类对象


    private void OnEnable()
    {
        chinarInspector = (ChinarInspector) target; //获取当前编辑自定义Inspector的对象(官方解释授检查的对象)
    }


    //通过对该方法的重写,可以对 Inspector 面板重新绘制,添加自己自定义GUI
    //既然说的自定义UI,就会覆盖我们关联脚本本身在面板的绘制
    public override void OnInspectorGUI()
    {
        //不写任何代码,ChinarInspector的面板上不出现任何属性
    }
}

OnEnable 函数,在 Editor 类中与 MonoBehavior 类中是完全不同的

调用时机EditorMonoBehavior
OnEnable1:每次聚焦 Unity 引擎窗口时脚本挂载的 GameObject 对象激活时
OnEnable2:点击 脚本挂载的 GameObject 对象时
OnEnable3:点击 Inspector,其他模块(例如scene面板)

举个例子

关联后的自定义脚本前在 Inspector 如下所示:
在这里插入图片描述


3

EditorGUILayout ―― 编辑器界面自动布局


  • EditorGUILayout :编辑器 UI 自动布局类,绘制的所有控件都具备自动布局(UI自适应)效果

GUILayout 的差异:

  • 拥有部分编辑器专用控件,
  • 只能运行在编辑器内
  • 自适应性较强

英文好的直接:EditorGUILayout 官方API链接

EditorGUILayout 只能在编辑器中使用,发布时是不会被打包

以下所有示例代码,都需要写到 OnInspectorGUI()函数中

  • 简单的示例,来向大家演示 EditorGUILayout 如何使 Inspector 面板更加直观,易用

举个例子

using UnityEditor;

/// <summary>
/// 编辑器类:用于对 ChinarInspector 做编辑器处理
/// </summary>
[CustomEditor(typeof(ChinarInspector))] //关联自定义编辑器脚本 ChinarInspector
public class ChinarEditor : Editor //自定义编辑器需要继承Editor
{
    private ChinarInspector chinarInspector; //关联目标对象

    private void OnEnable()
    {
        chinarInspector = (ChinarInspector) target; //获取当前编辑自定义 Inspector 的对象
    }

    /// <summary>
    /// 重绘 Inspector
    /// </summary>
    public override void OnInspectorGUI()
    {
       //以下所有绘制函数都写到这里
    }
}

3.1 EditorGUILayout.LabelField ―― 标签字段


  • EditorGUILayout.LabelField :标签字段。常用于显示文字描述,作提示使用
//制作一个标签字段。参数:label1标签字段前面的标签  label2显示在右侧的标签
EditorGUILayout.LabelField("定义信息","它只读不可写"); 

举个例子
在这里插入图片描述


3.2 EditorGUILayout.SelectableLabel ―― 可选择标签


  • SelectableLabel :可选择标签。常用于显示文字描述,作提示使用
  • LabelField 不同的是,它可以被复制,选择
//可选择标签。参数(显示信息)
EditorGUILayout.SelectableLabel("此标签可以被复制");

举个例子
在这里插入图片描述


3.3 EditorGUILayout.TextField ―― 文本框


  • TextField :文本输入框。填写我们需要的文本到框中
//将文本框中的文本信息,赋值到游戏对象名
//参数:label1 文本框提示信息  label2显示的文本
//返回值:显示的文本
chinarInspector.gameObject.name =  EditorGUILayout.TextField("定义信息", chinarInspector.gameObject.name);

举个例子
在这里插入图片描述


3.4 EditorGUILayout.PasswordField ―― 密码框


  • PasswordField :密码输入框。输入框为加密显示
    private string passwordText; //填充临时字符


    /// <summary>
    /// 重绘 Inspector
    /// </summary>
    public override void OnInspectorGUI()
    {
        //允许输入密码,并在下方显示明文(密码可见)
        //参数:label标签信息  password加密密码文本
        //返回:string
        passwordText = EditorGUILayout.PasswordField("Type Something", passwordText);
        EditorGUILayout.LabelField("显示密码", passwordText);
    }

举个例子
在这里插入图片描述


3.5 EditorGUILayout.IntField / FloatField ―― 整数、小数框


  • IntField :整数输入框。限制输入文本须为 Int 类型
  • FloatField :浮点数输入框。限制输入文本须为 float 类型
private int   intNumber   = 0; //输入的Int默认值和返回值
private float floatNumber = 0; //输入Float默认值和返回值


/// <summary>
/// 重绘 Inspector
/// </summary>
public override void OnInspectorGUI()
{
    intNumber   = EditorGUILayout.IntField("输入Int类型:", intNumber);       //IntField(标签名, 输入值),返回:Int
    floatNumber = EditorGUILayout.FloatField("输入Float类型:", floatNumber); //FloatField(标签名, 输入值),返回:Float
}

举个例子
在这里插入图片描述


3.6 EditorGUILayout.Slider ―― 滑动条


  • Slider :滑动条。默认滑动条,值为 Float 类型
  • IntSlider :整数滑动条。Int类型
  • MinMaxSlider :范围区域滑动条。设定最小-最大范围区间的滑动条。滑动值是一个范围

以下脚本,添加至 3.0 脚本模板

    private int   intValue;   //Intslider默认值和返回值
    private float floatValue; //slider默认值和返回值

    float minVal   = -10.0f; //区间滑动条:左侧默认值
    float minLimit = -20.0f; //最小值
    float maxVal   = 10.0f;  //右侧默认值
    float maxLimit = 20.0f;  //最大值


    /// <summary>
    /// 重绘 Inspector
    /// </summary>
    public override void OnInspectorGUI()
    {
        //整数滑动条
        intValue = EditorGUILayout.IntSlider("血量百分比", intValue, 0, 100); //参数(标签名,滑动值,最小值,最大值)
        //浮点数滑动条
        floatValue = EditorGUILayout.Slider("血量百分比", floatValue, 0, 100); //参数(标签名,滑动值,最小值,最大值)
        //区间滑动条
        EditorGUILayout.MinMaxSlider(ref minVal, ref maxVal, minLimit, maxLimit); //参数:(ref 左侧默认值,ref 右侧默认值,最小值,最大值)
        EditorGUILayout.LabelField("最小为:", minVal.ToString());
        EditorGUILayout.LabelField("最大为:", maxVal.ToString());
    }
  • ref可将变量 minVal、maxVal的值传递出去
  • 我们通过minVal - maxVal可得到滑动的一个区间值

举个例子
在这里插入图片描述


3.7 EditorGUILayout.Popup―― 弹出选择菜单


  • Slider :滑动条。默认滑动条,值为 Float 类型
  • IntSlider :整数滑动条。Int类型
  • MinMaxSlider :范围区域滑动条。设定最小-最大范围区间的滑动条。滑动值是一个范围
using UnityEditor;


/// <summary>
/// 编辑器类:用于对 ChinarInspector 做编辑器处理
/// </summary>
[CustomEditor(typeof(ChinarInspector))] //关联自定义编辑器脚本 ChinarInspector
public class ChinarEditor : Editor      //自定义编辑器需要继承Editor
{
    private ChinarInspector chinarInspector; //关联目标对象
    private bool            isList;          //


    private void OnEnable()
    {
        chinarInspector = (ChinarInspector) target; //获取当前编辑自定义 Inspector 的对象
    }


    /// <summary>
    ///Popup :弹出选择菜单
    /// </summary>
    private readonly string[] _playerNames = {"世界好小姐", "中国好声音甲组冠军", "Chinar网站创始人"}; //数据
    private int selectedIndex;                                                      //字段选项的索引


    /// <summary>
    /// IntPopup :弹出 Int 类型选择菜单
    /// </summary>
    private readonly string[] _ageNameArray = {"Chinar小学一年级时", "Chinar小学二年级时", "Chinar小学三年级时", "Chinar小学四年级时"}; //数据
    private readonly int[] _ages = {20, 21, 22, 23};                                                            // 设置 _ageNameArray 对应的int 组,用于返回
    private          int   selectedAgeIndex;                                                                    //字段选项的索引


    /// <summary>
    /// EnumPopup:弹出 枚举 选择菜单
    /// </summary>
    private enum GreatType //枚举类型
    {
        CUBE   = 0, //Cube类型
        SPHERE = 1, //Sphere类型
        PLANE  = 2  //Plane类型
    }


    private GreatType defaultGreatType; //默认枚举类型


    /// <summary>
    /// 重绘 Inspector
    /// </summary>
    public override void OnInspectorGUI()
    {
        //Popup - 弹出选择菜单
        //Popup(提示标签,选择索引,数据数组) 返回:Int
        selectedIndex = EditorGUILayout.Popup("选择菜单", selectedIndex, _playerNames);

        //IntPopup - 整数弹出选择菜单
        //IntPopup(提示标签,选择索引,数据数组,数据数组对应的 int 数组) 返回:int 数组中的对应 int 值
        selectedAgeIndex = EditorGUILayout.IntPopup("整数选择菜单: ", selectedAgeIndex, _ageNameArray, _ages);
        EditorGUILayout.LabelField("Chinar这个时候年纪是", selectedAgeIndex.ToString());

        //EnumPopup - 枚举弹出选择菜单
        //EnumPopup(提示标签,枚举对象) 返回:枚举类型
        defaultGreatType = (GreatType) EditorGUILayout.EnumPopup("Primitive to create:", defaultGreatType);
    }
}

举个例子
在这里插入图片描述


3.8

EditorGUILayout (Horizontal/Vertical) ―― 横向布局/纵向布局


  • BeginHorizontal :开始绘制横向布局,以 EndHorizontal 结束。两者成对出现
  • BeginVertical :开始绘制竖向布局,以 EndVertical 结束。两者成对出现

纵向布局就不提供代码了 ( 只需替换 BeginHorizontal 与 EndHorizontal )

using UnityEditor;


/// <summary>
/// 编辑器类:用于对 ChinarInspector 做编辑器处理
/// </summary>
[CustomEditor(typeof(ChinarInspector))] //关联自定义编辑器脚本 ChinarInspector
public class ChinarEditor : Editor      //自定义编辑器需要继承Editor
{
    private ChinarInspector chinarInspector; //关联目标对象


    private void OnEnable()
    {
        chinarInspector = (ChinarInspector) target; //获取当前编辑自定义 Inspector 的对象
    }


    /// <summary>
    /// 重绘 Inspector
    /// </summary>
    public override void OnInspectorGUI()
    {
        ChinarHorizontalLayout(); //横向布局
    }


    /// <summary>
    /// 横向布局写法
    /// </summary>
    private void ChinarHorizontalLayout()
    {
        EditorGUILayout.BeginHorizontal(); //开启一个横向布局 ——(注意一个设置布局的开始 对应一个布局的结束  EditorGUILayout.EndHorizontal)
        EditorGUILayout.Space();           //空行 (我们设置的横向布局 所以现在的空行 是横向的空行)
        EditorGUILayout.LabelField("位置1"); //设置文本描述
        EditorGUILayout.Space();
        EditorGUILayout.Space();
        EditorGUILayout.LabelField("位置2");
        EditorGUILayout.EndHorizontal(); //注意一个设置布局的开始 对应一个布局的结束 (与上面的 EditorGUILayout.BeginHorizontal() 对应起来)
    }
}

举个例子
横向布局效果图
在这里插入图片描述
纵向布局效果图
在这里插入图片描述





支持

May Be ―― 开发者,总有一天要做的事!


拥有自己的服务器,无需再找攻略

Chinar 提供一站式《零》基础教程

使有限时间 具备无限可能!

先点击领取 ―― 阿里全产品优惠券 (享受最低优惠)



Chinar 免费服务器、建站教程全攻略!( Chinar Blog )


Chinar

END

本博客为非营利性个人原创,除部分有明确署名的作品外,所刊登的所有作品的著作权均为本人所拥有,本人保留所有法定权利。违者必究

对于需要复制、转载、链接和传播博客文章或内容的,请及时和本博主进行联系,留言,Email: ichinar@icloud.com

对于经本博主明确授权和许可使用文章及内容的,使用时请注明文章或内容出处并注明网址

  • 7
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值