Unity插件开发笔记IMGUI-持续记录中

这篇具有很好参考价值的文章主要介绍了Unity插件开发笔记IMGUI-持续记录中。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

插件特点,无需运行可进行编译。

分为3大类插件:菜单项相关操作、自定义Inspector检视面板、自定义操作界面。

一.菜单项相关操作的插件分为4种:包含MenuItem菜单项插件、AddComponentMenu组件菜单插件、ContextMenu上下文菜单插件、RequireComponent必要组件菜单

1.MenuItem菜单项插件

(0)选项出现位置:编辑器上方菜单栏 。

(1)脚本放置的目录:Assets/Editor(该目录不会被打到包里)。

(2)创建如下方代码:需要命名空间UnityEditor;可自定义入口路径和自定义快捷键;MenuItem对应的自定义方法必须是static静态方法(方法在该脚本类的内部。static静态变量和静态方法是类中的静态成员,无论创建多少个类的对象,静态成员都只会存在一个,静态成员是不依赖于类的具体对象,可以通过类名.变量名(方法名)直接访问)。

(3)特点:无需放到场景里也无需运行,点击使用即可对MenuItem对应的函数进行编译。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;//MenuItem类插件需要该命名空间

public class MenuItem_Test1 : MonoBehaviour
{
    //快捷键类型(H是可自定义按键)
    //_H:单一个自定义按键
    //#H: Shift+自定义按键
    //%H:Ctrl+自定义按键
    //&H: Alt+自定义按键
    [MenuItem("Menu/Test_ _H")]//注册菜单选项:Menu/Test_是自定义的菜单路径,H是自定义的快捷键,放在该MenuItem_Test1类的里面
    public static void Test1()//定义MenuItem菜单操作:菜单必须是static静态方法
    {
        Debug.Log("Test_");
    }

    [MenuItem("Menu/Test# #H")]
    public static void Test2()
    {
        Debug.Log("Test#");
    }

    [MenuItem("Menu/Test% %H")]
    public static void Test3()
    {
        Debug.Log("Test%");
    }

    [MenuItem("Menu/Test& &H")]
    public static void Test4()
    {
        Debug.Log("Test&");
    }
}

2.AddComponentMenu组件菜单插件

(0)选项出现位置:节点上AddComponent增加组件时的可选组件列表里 。

(1)脚本放置的目录:一般在Assets/Script里(可自定义,会被打到包里的目录即可)。

(2)创建如下方代码:可自定义在添加组件时的菜单路径(放在该脚本类的前面)。

(3)特点:跟组件一样,需放到场景里也需运行,才可进行编译。

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

[AddComponentMenu("Menu/Test2")]//Test2是Component_Test1类脚本的组件名称,Menu/Test2是添加组件时的菜单路径,放在该Component_Test1类的前面
public class Component_Test1 : MonoBehaviour//定义Component操作
{
    void Start()
    {
        Debug.Log("Component_Test");
    }

    void Update()
    {
    }
}

3.ContextMenu上下文菜单插件

(0)选项出现位置:节点上的组件的右键菜单列表里 。

(1)脚本放置的目录:一般在Assets/Script里(可自定义,会被打到包里的目录即可)。

(2)创建如下方代码:可自定义在组件的右键菜单列表的菜单路径(放在该脚本类的内部)。

(3)特点:场景里需有所在的组件,但无需运行,点击使用即可进行编译。

using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;

[AddComponentMenu("Menu/Test2")]
public class Component_Test1 : MonoBehaviour
{
    void Start()
    {
        Debug.Log("Component_Test");
    }

    void Update()
    {
    }

    [ContextMenu("Menu3")]//Menu3是组件右键菜单列表里的路径,放在该Component_Test1类的内部
    public void Test()//定义ContextMenu菜单操作
    {
        Debug.Log("ContextMenu_Test");
    } 
}

4.RequireComponent必要组件菜单

(0)选项出现位置:无菜单,自动添加关联的必要组件。

(1)脚本放置的目录:一般在Assets/Script里(可自定义,会被打到包里的目录即可)。

(2)创建如下方代码:可自定义在添加组件时的菜单路径(放在该脚本类前面AddComponentMenu语句的前面)。

(3)特点:场景里需添加对应组件,无需运行,即可自动进行编译。

using System;
using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;

[RequireComponent(typeof(Rigidbody))]//设置该脚本类Component_Test1的必要组件菜单-Rigidbody(自定义的必要组件):添加该脚本,会自动添加Rigidbody组件。不算严格意义的组件,主要是给该脚本类设置关联。Rigidbody是依附于该脚本类Component_Test1的,需先删除本脚本,才能删除Rigidbody组件
[AddComponentMenu("Menu/Test2")]
public class Component_Test1 : MonoBehaviour
{
    void Start()
    {
        Debug.Log("Component_Test");
    }

    void Update()
    {
    }
}

二.自定义Inspector检视面板插件

1.常打的4种Attribute属性标识:HideInInspectory隐藏变量;NonSerialized不序列化保存;SerializeField序列化域;Serializable关键字序列化。

(还有许多其他的Attribute属性标识,还有odin插件的Attribute属性标识比IMGUI的Attribute属性标识的功能更全使用更简单。)

(1)HideInInspectory隐藏变量:隐藏公有变量属性显示。

(2)NonSerialized不序列化保存:隐藏公有变量属性显示且不序列化保存。需要using System;命名空间。

(3)SerializeField序列化域:强制显示私有变量且序列化保存。

(4)Serializable可序列化的:需要在Type1类的定义前面设置,会把该类的公有变量在这里也序列化。

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

public class Component_Test2 : MonoBehaviour
{
    public int Int1=3;//正常公有变量(默认情况下:公有变量会序列化,私有变量不会序列化;序列化指显示在界面组件上且会存储到硬盘上)

    [HideInInspector]//HideInInspector:隐藏公有变量属性显示。
    public int Int2=3;

    [NonSerialized]//NonSerialized:隐藏公有变量显示,防止变量序列化保存。需要using System;的命名空间。
    public int Int3=3;

    [SerializeField]//SerializeField:序列化域。强制显示私有变量,且序列化保存到硬盘上。
    private int Int4;

    //[Serializable]:关键字序列化。需要在Type1类的定义前面设置,会把该类的公有变量在这里也序列化。
    public Type1 mType=new Type1();

    void Start()
    {
    }

    void OnGUI()
    {
    }
}
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[Serializable]//关键字序列化。需要在对应Type1类的定义前面设置,会把该类的公有变量在其他地方新建该类的时候也序列化。
public class Type1 //不挂在界面里的节点上,所以不用继承MonoBehaviour
{
    public int InitVal;
    public float FloatVal;
    private Color mColor;
    void Start()
    {
    }

    void Update()
    {
    }
}

2.自定义界面属性

(1)被自定义属性界面的类:在挂在界面节点上,继承MonoBehaviour,脚本放置在Assets/Script(可自定义,会被打到包里的目录即可)。

       1) 属性类型、自定义class类方法里的属性等都在该脚本里定义

        2)自定义class类方法前面需打可被序列化的Attribute属性标识:[System.Serializable]

(2)自定义绘制界面属性类:新建一个C#脚本,继承自Editor(需要using UnityEditor;命名空间),脚本放置在Assets/Editor(该目录不会被打到包里)。

        1)继承自Editor的类前面需打关联上被自定义属性界面(序列化对象)的Attribute属性标识:[CustomEditor(typeof(被自定义属性界面的类),true)]。

        2)声明序列化对象SerializedObject,和声明序列化属性SerializedProperty

        3)在OnEnable()函数里初始化赋值以上的序列化对象和序列化属性:新建序列化对象,FindProperty序列化属性

        4)在override void OnInspectorGUI()复写Editor的绘制函数里:先更新序列化对象Update,再自定义绘制序列化属性EditorGUILayout.PropertyField,再让序列化对象应用自定义绘制ApplyModifiedProperties

        5)在override void OnInspectorGUI()复写Editor的绘制函数里的默认绘制语句:base.OnInspectorGUI();//表示按照Editor默认的行为将所有的序列化属性绘制出来:属性面板包含默认的绘制+本脚本的绘制。 如果去掉这句话, 属性面板上只会绘制脚本的名字+本脚本的绘制。

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

public class Test3 : MonoBehaviour//挂界面节点上的脚本,继承MonoBehaviour
{
    public int IntVal;
    public float FloatVal;
    public string StrVal;

    public Type3 Type3Val=new Type3();//引用类型class,需要实例化出一个对象“带()”
    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        
    }
}

[System.Serializable]//在Test3_Window窗口绘制脚本里需要序列化,所以这里需要设置成可序列化的
public class Type3//class是引用类型
{
    public int mInt;
    public int mInt2;
}
using System.Collections;
using System.Collections.Generic;
using UnityEditor;//继承Editor类,需要改命名空间
using UnityEngine;

[CustomEditor(typeof(Test3),true)]//把Test3类的属性关联到本编辑界面,Test3是继承了MonoBehavior脚本的类(当然还有其它类);第2个参数指是否对其子类生效
public class Test3_Inspoector : Editor//不挂在界面里的节点上,所以不用继承MonoBehaviour。本编辑界面需继承Editor类,需要using UnityEditor;命名空间。放在Asset/Editor目录下,不打入包内。
{
    public SerializedObject mObj;//SerializedObject序列化对象类型
    public SerializedProperty mInt;//SerializedProperty序列化通用属性类型
    public SerializedProperty mFloat;
    public SerializedProperty mStr;
    public SerializedProperty mType3;

    //选择当前脚本所在的游戏对象时执行
    public void OnEnable()
    {
        this.mObj=new SerializedObject(target);//这里的target指被检视的Object对象Test3类,这里时用被检视的Object对象新建序列化对象
        this.mInt=this.mObj.FindProperty("IntVal");//FindProperty查找序列化对象中的已有属性,然后赋值给序列化属性
        this.mFloat=this.mObj.FindProperty("FloatVal");
        this.mStr=this.mObj.FindProperty("StrVal");
        this.mType3=this.mObj.FindProperty("Type3Val");
    }

    //显示绘制本编辑界面
    public override void OnInspectorGUI()//override指是重写父类的方法,OnInspectorGUI方法会在对象获得焦点或者对象属性变化或者其他一些情况下调用
    { 
        //base.OnInspectorGUI();//表示按照Editor默认的行为将所有的序列化属性绘制出来:属性面板包含默认的绘制+本脚本的绘制。 如果去掉这句话, 属性面板上只会绘制脚本的名字+本脚本的绘制。
        
        //更新一下序列化对象,以免数据未同步
        this.mObj.Update();

        //重载:绘制属性到Inspector检视面板里
        EditorGUILayout.PropertyField(this.mInt);//EditorGUILayout.PropertyField:按照默认行为绘制该字段
        EditorGUILayout.PropertyField(this.mFloat);
        //EditorGUILayout.PropertyField(this.mStr);
        EditorGUILayout.PropertyField(this.mType3,true);//第2个参数true指包括子节点,现在默认就是包括的了所以不设置也可以

        //序列化对象应用修改的属性
        this.mObj.ApplyModifiedProperties();//ApplyModifiedProperties的返回值能够表明序列化字段是否有修改,返回true代表有修改
    }
}

3.自定义序列化属性字段(枚举enum+switch方法实现多类型选一显示)

(1)被自定义属性界面的类:Test4 ,说明同上“2.自定义界面属性”。多定义了一个枚举类型。
(2)自定义绘制界面属性类:Test4_EditorInspector ,说明同上“2.自定义界面属性”。多用了一个Switch方法。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public enum Enum4//enum枚举类型:会在编译阶段将名字替换成对应的整数常量(从0开始),是预处理指令宏#define的替代
{
    None,
    IntVal,
    FloatVal,
    StrVal,
    ColorVal
}//None/IntValue/FloatVal/StrValColorVal是全局常量,其他地方不可有相同名字的变量或常量
public class Test4 : MonoBehaviour
{
    public Enum4 mEnum;//在上方定义
    public int mInt;
    public float mFloat;
    public string mStr;
    public Color mColor;
    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;

[CustomEditor(typeof(Test4))]//把该属性视图面板Test4_EditorInspector定义到Test4里
public class Test4_EditorInspector : Editor
{
    public SerializedObject mObj;
    public SerializedProperty mEnum;
    public SerializedProperty mInt;
    public SerializedProperty mFloat;
    public SerializedProperty mStr;
    public SerializedProperty mColor;
    public void OnEnable()
    {
        //初始化
        this.mObj=new SerializedObject(target);

        this.mEnum=this.mObj.FindProperty("mEnum");
        this.mInt=this.mObj.FindProperty("mInt");
        this.mFloat=this.mObj.FindProperty("mFloat");
        this.mStr=this.mObj.FindProperty("mStr");
        this.mColor=this.mObj.FindProperty("mColor");
    }

    public override void OnInspectorGUI()
    {
        this.mObj.Update();//序列化对象更新

        //自定义绘制
        EditorGUILayout.PropertyField(this.mEnum);
        switch(this.mEnum.enumValueIndex)//开关语句
        {
            case 1:
                EditorGUILayout.PropertyField(this.mInt);//EditorGUILayout.PropertyField属性绑定绘制
                break;
            case 2:
                EditorGUILayout.PropertyField(this.mFloat);
                break;
            case 3:
                EditorGUILayout.PropertyField(this.mStr);
                break;
            case 4:
                EditorGUILayout.PropertyField(this.mColor);
                break;
        }

        this.mObj.ApplyModifiedProperties();//序列化对象应用自定义的修改
    }
}

三.自定义操作界面(类似Animation这种弹出的界面)

(0)选项出现位置:编辑器上方菜单栏 。

(1)脚本放置的目录:Assets/Editor(该目录不会被打到包里)。

(2)创建如下方代码:类名=窗口界面名;继承EditorWindow父类,需要命名空间UnityEditor;可用MenuItem自定义入口路径和自定义快捷键;MenuItem对应的自定义方法必须是static静态类方法(放在该脚本类的内部)。

(3)特点:无需放到场景里也无需运行,点击使用即可对MenuItem对应的函数进行编译。

1.界面的启动关闭-常用的EditorWindow的3种方法:

(1)Show:面板显示方法:跟Game窗口同级,可合并到编辑器面板里。可拖动,自带关闭按钮。

(2)ShowUtility:浮动显示方法:跟编辑器界面同级,不可合并到编辑器面板里。可拖动,自带关闭按钮。

(3)ShowPopup:不可拖动,需要手动增加绘制关闭按钮。

using System.Collections;
using System.Collections.Generic;
using UnityEditor;//EditorWindow弹出窗口类需要该命名空间
using UnityEngine;

public class Test5_Window : EditorWindow//EditorWindow弹出窗口类,需要using UnityEditor;命名空间
{
    [MenuItem("Menu/ShowTest5Window")]//注册菜单选项:在unity菜单栏里,增加执行下面ShowWindow函数的菜单项
    public static void ShowWindow()
    {
        //(1)面板显示方法:跟Game窗口同级,可合并到编辑器面板里。可拖动,自带关闭按钮
        Test5_Window.CreateInstance<Test5_Window>().Show();//创建窗口:实例化出一个窗口对象,点击菜单多次则创建多个相同的窗口。CreateInstance是窗口的官方实例化接口
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;

public class Test5_Window : EditorWindow
{
    [MenuItem("Menu/ShowTest5Window")]
    public static void ShowWindow()
    {
        //(2)浮动显示方法:跟编辑器界面同级,不可合并到编辑器面板里。可拖动,自带关闭按钮
        Test5_Window.CreateInstance<Test5_Window>().ShowUtility();
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;

public class Test5_Window : EditorWindow
{
    [MenuItem("Menu/ShowTest5Window")]
    public static void ShowWindow()
    {
        //(3)弹窗显示方法:不可拖动,需要手动增加绘制关闭按钮
        Test5_Window.CreateInstance<Test5_Window>().ShowPopup();
    }
    public void OnGUI()//自动执行的绘制函数
    {
        if(GUILayout.Button("关闭"))//GUILayout.Button绘制按钮
        {
            this.Close();//关闭界面
        }
    }
}

2.界面的相关事件机制(内置函数自动调用):

(1)单例形式创建窗口:EditorWindow.GetWindow。
(2)界面的事件机制:生命周期(也叫消息Message、必然事件)-常用事件监听有以下9种OnGUI(类似Update每帧调用)、Update、OnInspectorUpdate、OnDestroy、OnSelectionChange、OnFocus、OnLostFocus、OnHierarchyChange、OnHierarchyChange。
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;

public class Test6_Window : EditorWindow//继承EditorWindow类
{
    [MenuItem("Menu/ShowTest6Window")]//注册菜单选项
    public static void ShowWindow()//单例形式创建窗口
    {
        //创建窗口:实例化出一个窗口对象,点击菜单多次则创建多个相同的窗口。CreateInstance是窗口的官方实例化接口
        //Test6_Window.CreateInstance<Test6_Window>().Show();

        //单例形式创建窗口:点击菜单多次,也只打开一个Test6_Window窗口
        EditorWindow.GetWindow<Test6_Window>().Show();//获取Test6_Window本类型已打开窗口界面的第一个,然后把Test6_Window传递进去,然后Show显示出来
    }

    
    //界面的事件机制:生命周期(也叫消息Message、必然事件)-常用事件监听有以下9种OnGUI、Update、OnInspectorUpdate、OnDestroy、OnSelectionChange、OnFocus、OnLostFocus、OnHierarchyChange、OnHierarchyChange。
    
    //界面绘制方法:绘制操作面板上的内容,比如按钮
    public void OnGUI()
    {
        if(GUILayout.Button("关闭"))
        {
            this.Close();
        }
    }

    //界面刷新方法:刷新周期每秒钟执行100次
    public void Update()
    {
        //index_1++;
    }

    public int index_1=0;
    //检视面板刷新方法:刷新周期比Update小
    public void OnInspectorUpdate()
    {  
        //Debug.Log("index_1:"+index_1+"\n"+"index_2:"+(index_2++));
    }

    public int index_2=0;
    //本视图面板被删除时,触发该事件并自动调用该方法
    public void OnDestroy()
    {
        Debug.Log("删除");
    }

    //在Hierarchy视图面板选择一个节点或者在Project视图面板里选择一个文件时,触发该事件并自动调用该方法
    public void OnSelectionChange()
    {
        //Debug.Log("在Hierarchy或Project选择一个对象");
        /*for(int i=0;i<Selection.gameObjects.Length;i++)//Selection.gameObjects:仅获取Hierarchy视图面板里目前选择的对象,即场景里的对象
        {
            Debug.Log("选择场景里的对象:"+Selection.gameObjects[i].name);
        }*/
        for(int i=0;i<Selection.objects.Length;i++)//Selection.objects:获取Hierarchy和Project视图面板里目前选择的对象
        {
            Debug.Log("选择对象:"+Selection.objects[i].name);
        }
    }

    //本视图面板获取焦点时,触发该事件并自动执行该方法
    public void OnFocus()
    {
        Debug.Log("本窗口获取焦点");
    }

    //本视图面板失去焦点时,触发该事件并自动执行该方法
    public void OnLostFocus()
    {
        Debug.Log("本窗口失去焦点");
    }

    //Hierarchy视图面板有任何更改时,触发该事件并自动执行该方法,但是组件里的属性数值发生变化不会触发
    public void OnHierarchyChange()
    {
        Debug.Log("Hierarchy有更改");
    }

    //Project视图面板有任何更改时,触发该事件并自动执行该方法
    public void OnProjectChange()
    {
        Debug.Log("Project有更改");
    }
}

3.文本和颜色字段-EditorGUILayout的方法

(1)文本输入字段-常用有3种:TextField单行输入框、TextArea多行输入框、PasswordField加密输入框。
(2)颜色选择字段:ColorField。
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;

public class Test7_Window : EditorWindow
{
    [MenuItem("Menu/ShowTest7Window")]
    public static void ShowWindow()
    {
        EditorWindow.GetWindow<Test7_Window>().Show();//EditorWindow单例形式打开界面
    }
    
    public string mText="默认文本";//用于存储输入的文本内容,保证创建文本输入框时的文本是输入的文本
    public Color mColor=Color.white;//用于存储修改的颜色值,保证创建颜色输入框时的颜色是输入的颜色
    public void OnGUI()//自动绘制函数
    {
        //EditorGUILayout创建一个输入框:重载输入一个字符串,同时也会返回一个字符串。重载就是一个类中有N个重名函数,但是他们的参数类型或者个数不相同,当然顺序不相同也是可以的,调用的时候,会自动根据你填写的参数类型,个数来调用匹配的重载(注意:和返回值木有任何关系)
        this.mText=EditorGUILayout.TextField(this.mText);//文本单行输入框字段
        this.mText=EditorGUILayout.TextArea(this.mText);//文本多行输入框字段
        this.mText=EditorGUILayout.PasswordField(this.mText);//文本单行密码输入框字段

        this.mColor=EditorGUILayout.ColorField(this.mColor);//颜色选择字段
    }
}

4.Lable标签和换行字段(这里标签是给属性增加前缀名字)-EditorGUILayout的方法

(1)Lable标签前缀字段-常用有3种:LabelField静态标签前缀、SelectableLabel可选择标签前缀、PrefixLabel可聚焦不可选择标签前缀。
(2)空一行字段:Space。
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;

public class Test8_Window : EditorWindow
{
    [MenuItem("Menu/ShowTest8Window")]
    public static void ShowWindow()
    {
        EditorWindow.GetWindow<Test8_Window>().Show();//EditorWindow单例形式打开界面
    } 
    
    public string mText="默认文本";
    public Color mColor=Color.white;
    public void OnGUI()
    {
        EditorGUILayout.LabelField("文本标签");//EditorGUILayout.LabelField:不可选择的文本标签字段,不能更改。
        this.mText=EditorGUILayout.TextField(this.mText);

        EditorGUILayout.SelectableLabel("可选择文本标签");//EditorGUILayout.SelectableLabel:可选择的文本标签字段,不能更改。上下会自动空行
        this.mText=EditorGUILayout.TextArea(this.mText);

        EditorGUILayout.PrefixLabel("可焦点但不可选择文本标签");//EditorGUILayout.PrefixLabel:可作为焦点但不可选择文本标签字段,不能更改。
        this.mText=EditorGUILayout.PasswordField(this.mText);

        EditorGUILayout.Space();//EditorGUILayout.Space:空一行字段。
        this.mColor=EditorGUILayout.ColorField(this.mColor);
    }
}

5.数字输入字段-EditorGUILayout的方法

(1)浮点型数字输入字段:FloatField

(2)整形数字输入字段:IntField

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

public class Test9_Window : EditorWindow
{
    [MenuItem("Menu/Show Test9Window")]
    public static void ShowWindow()
    {
        EditorWindow.GetWindow<Test9_Window>().Show();
    }

    public float mFloat;//用于存储输入的浮点数,保证创建浮点形数字输入框时的数值是输入的数值
    public int mInt;//用于存储输入的整数,保证创建整形数字输入框时的数值是输入的数值
    public void OnGUI()
    {
        EditorGUILayout.LabelField("浮点形数字输入框:");
        this.mFloat=EditorGUILayout.FloatField(this.mFloat);//浮点形数字输入框字段,单精度类型,保留7位有效数字

        EditorGUILayout.Space();
        EditorGUILayout.PrefixLabel("整形数字输入框:");
        this.mInt=EditorGUILayout.IntField(this.mInt);//整形数字输入框字段
    }
}

6.滑动条字段-EditorGUILayout的方法

(1)默认浮点型滑动条字段:Slider

(2)整形滑动条字段:IntSlider

(3)有长度的滑动条字段:MinMaxSlider

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

public class Test10_Window : EditorWindow
{
    [MenuItem("Menu/ShowTest10Window")]
    public static void ShowWindow()
    {
        EditorWindow.GetWindow<Test10_Window>().Show();
    }

    public float mFloat;//用于存储滑动条设置的浮点数,保证创建滑动条时的当前数值是设置的数值
    public int mInt;//用于存储滑动条设置的整数,保证创建整数形滑动条时的当前数值是设置的数值

    public float mMinVal;//用于存储MinMaxSlider的有长度滑动条的左端的值
    public float mMaxVal;//用于存储MinMaxSlider的有长度滑动条的右端的值
    public void OnGUI()
    {
        //默认滑动条(浮点型)
        EditorGUILayout.LabelField("默认浮点型滑动条:");
        this.mFloat=EditorGUILayout.Slider(this.mFloat,0,10);//3个参数:默认值,最小值,最大值;会返回一个浮点型数值
    
        //整数型滑动条
        EditorGUILayout.LabelField("整形滑动条:");
        this.mInt=EditorGUILayout.IntSlider(this.mInt,0,10);//3个参数:默认值,最小值,最大值;会返回一个整型数值

        EditorGUILayout.Space();
        this.mMinVal=EditorGUILayout.Slider(this.mMinVal,0,10);//用于显示设置下面MinMaxSlider左端的数值
        this.mMaxVal=EditorGUILayout.Slider(this.mMaxVal,0,10);//用于显示设置下面MinMaxSlider右端的数值
        //最小最大限制滑动条(滑动条自身有长度)
        EditorGUILayout.LabelField("有长度的滑动条:");
        EditorGUILayout.MinMaxSlider(ref this.mMinVal,ref this.mMaxVal,1,10);//4个参数:第一个参数-有长度的滑动条左端点的值,第二个参数-有长度的滑动条右端点的值,最小值,最大值。ref是指引用类型的参数,引用传递是传递变量的地址,使得形参和实参指向同一内存空间,方法中对于形参的修改,实际上就是对实参的修改。调用方法时初始化参数值。
    }
}

7.位置 宽高大小输入字段-EditorGUILayout的方法

(1)坐标设置字段:Vector2Field二维坐标,Vector3Field三位坐标,Vector4Field思维坐标

(2)矩阵设置字段:RectField,可设置二维坐标X Y和宽高W H

(3)间距区设置字段:BoundsField,可设置两个三维坐标系-中心点坐标(X,Y,Z) 和间隔区域的宽高深(X,Y,Z)

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

public class Test11_Window : EditorWindow
{
    [MenuItem("Menu/ShowTest11Window")]
    public static void ShowWindow()
    {
        EditorWindow.GetWindow<Test11_Window>().Show();
    }

    public Vector2 mPos2;//用于存储设置的2维向量
    public Vector3 mPos3;//用于存储设置的3维向量
    public Vector4 mPos4;//用于存储设置的4维向量
    public Rect mRect;//用于存储设置的矩阵类型
    public Bounds mBounds;//用于存储设置的边距类型

    public void OnGUI()
    {
        //自带标签前缀参数
        this.mPos2=EditorGUILayout.Vector2Field("二维坐标:",this.mPos2);//2个参数:标签名字前缀,二维变量(X,Y)
        this.mPos3=EditorGUILayout.Vector3Field("三维坐标:",this.mPos3);//2个参数:标签名字前缀,三维变量(X,Y,Z)
        this.mPos4=EditorGUILayout.Vector4Field("四维坐标:",this.mPos4);//2个参数:标签名字前缀,四维变量(X,Y,Z,W)

        EditorGUILayout.Space();
        EditorGUILayout.LabelField("矩阵:");
        this.mRect=EditorGUILayout.RectField(this.mRect);//矩阵类型变量(X,Y)(W,H)

        EditorGUILayout.Space();
        EditorGUILayout.LabelField("间距:");
        this.mBounds=EditorGUILayout.BoundsField(this.mBounds);//两个三维坐标系:中心点坐标(X,Y,Z),和间隔区域(X,Y,Z)
    }
}

8.单选弹出菜单选择字段-EditorGUILayout的方法

(1)单选弹出菜单字段:Popup,需重载2个参数,(接收返回值类型,选项字符串数组),需要定义字符串数组。

(2)整形单选弹出菜单字段:IntPopup,需重载3个参数(接收返回值类型,选项字符串数组,选项序号整型数组),需要定义字符串数组和整形数组。因为返回值可在整形数组里自定义,所以功能比其他两种强大。

(3)枚举型单选弹出菜单字段:EnumPopup,只需重载1个参数,需要定义枚举。返回值赋值需要强制转换成定义的枚举类型。

using System;//Int32类型需要该命名空间
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;

public enum Enum12:Int32//定义EnumPopup选项对应的枚举成员描述性名称(即成员)。enum枚举类型:本身是值类型,但是父类System.Enum是引用类型(引用类型不是传递值而是传递引用,共享引用的原始对象,其他引用类型如节点GameObject/组件Component/资源Asset),枚举类型是一组命名整型常量(定义时可在名字后面加“:数据类型”来显式指定枚举的底层数据类型,缺省时为int32类型),包含自己的值(默认为0),可用成员名给其赋值;枚举的成员实际对应的值都是整型,枚举成员描述性名称不能相同,对应的值可相同(但值相同的情况下只能指向第一个该值的成员)。
{
    Int1,
    Str2,
    Float3=1,//枚举成员的索引值从0开始:Int1=0,Str2=1;现在Float3也=1,则Enum12.Float3打印出来是“Str2”
    Color4
}
public class Test12_Window : EditorWindow
{
    [MenuItem("Menu/ShowTest12Window")]
    public static void ShowWindow()
    {
        EditorWindow.GetWindow<Test12_Window>().Show();
    }

    public int index;//用于存储Popup所选择的索引值
    public Enum12 mEnum;//用于存储EnumPopup所选择的枚举。默认值是一个整数,如果有对应该整数的成员名,则值是成员名(如果有对应相同整数的多个成员名,则赋值成对应该整数的第1个成员
    public void OnGUI()
    {
        EditorGUILayout.LabelField("单选弹出菜单:");
        string[] strs=new string[]{"werwer1","werwer2","werwer3","werwer4","werwer5"};//提前自定义Popup单选的可选择项的字符串数组
        this.index=EditorGUILayout.Popup(this.index,strs);//字符型单选弹出菜单(选择器)。2个参数:当前所选项的序号,可选项的字符串数组。返回值:字符串数组当前选择的索引值。

        EditorGUILayout.LabelField("整形单选弹出菜单:");
        int[] ints=new int[]{11,12,13,14,15};
        this.index=EditorGUILayout.IntPopup(this.index,strs,ints);//整型单选弹出菜单(选择器):因为返回值可在整形数组里自定义,所以功能比其他两种强大。3个参数:当前所选项的序号,可选项的字符串名称数组,可选项的整形数组。返回值:整型数组当前选择的值。
        
        EditorGUILayout.LabelField("枚举型单选弹出菜单:");
        this.mEnum=(Enum12)EditorGUILayout.EnumPopup(this.mEnum);//枚举型单选弹出菜单(选择器):可以只用一个重载参数,使用比较方便。返回值:枚举类型成员的描述性名称,需要强制转换。
        Debug.Log(Enum12.Float3);
    } 
}

9.Tag标签 Layer层 对象的选择字段(这里标签是给对象设置Tag)-EditorGUILayout的方法

(1)Tag标签选择字段:TagField,跟Inspctor检视面板上的Tag的功能和预设选项完全一样。

(2)Layer层选择字段:LayerField,跟Inspctor检视面板上的Layer的功能和预设选项完全一样,没写层名称的索引值不能被设置(选择AddLayer...选项后,Inspctor检视面板上在能看都哪些值设置了层名称)。

(3)对象选择字段:ObjectField,3个参数(旧版2个参数),第一个参数是Object类型;第二个参数是限制可选的类型(例如Object是所有的对象,Transform是所有带有Transform组件的对象);第三个参数allowSceneObjects是指是否允许选择场景中的对象(GameObject类型的,或者在Hierarchy面板里的)设置成true的话选项会多一个Scene的页签,设置成false只有一个Asset页签(官方API说明:如果对象引用作为资源的一部分进行存储,请确保 allowSceneObjects 参数为 false,因为资源无法存储对场景中对象的引用。)

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

public class Test13_Window : EditorWindow
{
    [MenuItem("Menu/ShowTest13Window")]
    public static void ShowWindow()
    {
        EditorWindow.GetWindow<Test13_Window>().Show();
    }

    public string mString;//用于存储TagField选择的标签名称字符串(即返回值)
    public int mInt;//用于存储LayerField选择的层索引值(即返回值),没写层名称的索引值不能被设置(选择AddLayer...选项后,Inspctor检视面板上在能看都哪些值设置了层名称)
    public Object mObject;//用于存储ObjectField选择的对象(即返回值)。Object类型的对象:可以是场景里的(Hierarchy面板里的),也可以不在场景里(Project面板里的)。GameObject对象:必须在场景里(在Hierarchy面板里)。
    public void OnGUI()
    {
        this.mString=EditorGUILayout.TagField(this.mString);//TagField标签选择器:跟Inspctor检视面板上的Tag的功能和预设选项完全一样
        this.mInt=EditorGUILayout.LayerField(this.mInt);//LayerField标签选择器:跟Inspctor检视面板上的Layer的功能和预设选项完全一样
        
        this.mObject=EditorGUILayout.ObjectField(this.mObject,typeof(Transform),true);//ObjectField对象选择器:3个参数(旧版2个参数),第一个参数是Object类型;第二个参数是限制可选的类型(例如Object是所有的对象,Transform是所有带有Transform组件的对象);第三个参数allowSceneObjects是指是否允许选择场景中的对象(GameObject类型的,或者在Hierarchy面板里的)设置成true的话选项会多一个Scene的页签,设置成false只有一个Asset页签(官方API说明:如果对象引用作为资源的一部分进行存储,请确保 allowSceneObjects 参数为 false,因为资源无法存储对场景中对象的引用。)
    }
}

10. 勾选框和折叠按钮字段-EditorGUILayout的方法

(1)勾选框字段:Toggle

(2)折叠按钮字段:Foldout,2个参数,第二个参数是前缀标签,返回值是布尔值。

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

public class Test14_Window : EditorWindow
{
    [MenuItem("Menu/ShowTest14Window")]
    public static void ShowWindow()
    {
        EditorWindow.GetWindow<Test14_Window>().Show();
    }

    public bool mBool;//用于存储Toggle或Foldout的返回值
    public void OnGUI()
    {
        EditorGUILayout.LabelField("单个勾选框:");
        this.mBool=EditorGUILayout.Toggle(this.mBool);//单个勾选框:1个参数(旧版有俩参数,第一个参数是前缀标签),返回值是布尔值。
    
        EditorGUILayout.LabelField("折叠展开按钮:");
        this.mBool=EditorGUILayout.Foldout(this.mBool,"折叠");//折叠展开按钮:2个参数,第二个参数是前缀标签,返回值是布尔值。
        if(this.mBool)//展开时才渲染下面的内容
        {
            EditorGUILayout.LabelField("标签1");
            EditorGUILayout.LabelField("标签2");
            EditorGUILayout.LabelField("标签3");
            EditorGUILayout.LabelField("标签4");
            EditorGUILayout.LabelField("标签5");
        }
    }
}

11.分组字段(都是Begin与End俩字段一起使用)-EditorGUILayout的方法

(1)勾选开启关闭分组字段:BeginToggleGroup和EndToggleGroup。2个参数-前缀标签和是否勾选可开启设置的bool。返回是否开启设置的bool值

(2)水平排版分组字段:BeginHorizontal和EndHorizontal。没有参数,返回绘制区域的Rect。

(3)垂直排版分组字段:BeginVertical和EndVertical。没有参数,返回绘制区域的Rect(默认就是垂直排版,但是可返回Rect)。

(4)滚动分组字段:BeginScrollView和EndScrollView。1个参数-Vector2类型的偏移量,返回Vector2类型的滚动偏移量。一般用于整个窗口内容,当窗口变小不足以显示内容时,可自适应出现上下或者左右滚动。

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

public class Test15_Window : EditorWindow
{
    [MenuItem("Menu/ShowTest15Window")]
    public static void ShowWindow()
    {
        EditorWindow.GetWindow<Test15_Window>().Show();
    }

    public string mString;
    public bool mBool;//存储BeginToggleGroup返回的bool值
    public Vector2 mVector2;//存储BeginScrollView返回的2维坐标值
    public void OnGUI()
    {
        this.mBool=EditorGUILayout.BeginToggleGroup("勾选开启关闭分组",this.mBool);//开始勾选框的分组
        EditorGUILayout.LabelField("标签1");
        this.mString=EditorGUILayout.TextField(this.mString);
        EditorGUILayout.LabelField("标签2");
        this.mString=EditorGUILayout.TextField(this.mString);
        EditorGUILayout.EndToggleGroup();//结束勾选框的分组

        EditorGUILayout.Space();

        EditorGUILayout.LabelField("水平排版分组:");
        Rect rectH=EditorGUILayout.BeginHorizontal();//开始水平排版分组。返回绘制区域的Rect
        Debug.Log(rectH);
        EditorGUILayout.LabelField("标签3");
        this.mString=EditorGUILayout.TextField(this.mString);
        EditorGUILayout.LabelField("标签4");
        this.mString=EditorGUILayout.TextField(this.mString);
        EditorGUILayout.EndHorizontal();//结束水平排版分组

        EditorGUILayout.Space();

        EditorGUILayout.LabelField("垂直排版分组:");
        Rect rectV=EditorGUILayout.BeginVertical();//开始垂直排版分组。返回绘制区域的Rect(默认就是垂直排版,但是可返回Rect)
        Debug.Log(rectV);
        EditorGUILayout.LabelField("标签5");
        this.mString=EditorGUILayout.TextField(this.mString);
        EditorGUILayout.LabelField("标签6");
        this.mString=EditorGUILayout.TextField(this.mString);
        EditorGUILayout.LabelField("标签7");
        this.mString=EditorGUILayout.TextField(this.mString);
        EditorGUILayout.EndVertical();//结束垂直排版分组

        EditorGUILayout.Space();

        EditorGUILayout.LabelField("滚动分组:");
        this.mVector2=EditorGUILayout.BeginScrollView(this.mVector2);//开始滚动分组。一般用于整个窗口内容,当窗口变小不足以显示内容时,可自适应出现上下或者左右滚动。返回滚动的偏移量。
        Debug.Log(this.mVector2);
        EditorGUILayout.LabelField("标签8");
        this.mString=EditorGUILayout.TextField(this.mString);
        EditorGUILayout.LabelField("标签9");
        this.mString=EditorGUILayout.TextField(this.mString);
        EditorGUILayout.LabelField("标签10");
        this.mString=EditorGUILayout.TextField(this.mString);
        EditorGUILayout.EndScrollView();//结束滚动分组
    }
}

12.动画曲线和Inspector检视视图标题栏设置字段-EditorGUILayout的方法

(1)动画曲线字段:CurveField。返回的AnimationCurve类型值,创建该AnimationCurve类型变量时需要new初始化一下。该曲线设置一般由Animation动画引用。

(2)Inspector检视视图标题栏设置字段:InspectorTitlebar。返回是否折叠的布尔值。2个参数:第一个参数是是否折叠(可以跟折叠按钮字段Foldout一样,用返回的bool值加个判断,通过自定义属性把目标对象的属性搬到被折叠的这里),第二个参数是显示的目标对象(最好给第二个对象类型的参数加一下非空保护判断:当对象不为空时,再会绘制下面的InspectorTitlebar)。文章来源地址https://www.toymoban.com/news/detail-794786.html

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

public class Test16_Window : EditorWindow
{
    [MenuItem("Menu/ShowTest16Window")]
    public static void ShowWindow()
    {
        EditorWindow.GetWindow<Test16_Window>().Show();
    }

    public AnimationCurve mAnimationCurve=new AnimationCurve();//存储CurveField返回的AnimationCurve值。需要new初始化。AnimationCurve的成员当前帧数Keyframe(时间,值,值的的切线输入值,值的切线输出值)
    public bool mBool;//存储InspectorTitlebar返回的bool值。
    public Object mObject; //存储ObjectField返回的Object对象。
    public void OnGUI()
    {
        EditorGUILayout.LabelField("动画曲线设置:");
        this.mAnimationCurve=EditorGUILayout.CurveField(this.mAnimationCurve);//动画曲线字段:一般由Animation动画引用

        EditorGUILayout.Space();

        EditorGUILayout.LabelField("Inspector检视视图标题栏设置:");
        this.mObject=EditorGUILayout.ObjectField(this.mObject,typeof(Object),true);//这里是为了给下面InspectorTitlebar的第二个Object类型的参数赋值,这里ObjectField的第二个参数typeof(XXX)会控制下面InspectorTitlebar显示出来的组件,这里设成Button下面就是显示Button组件的标题头部
        if(this.mObject!=null)//加个非空保护:防止对象为空导致报错。当对象不为空时,才会绘制下面的InspectorTitlebar
        {
            this.mBool=EditorGUILayout.InspectorTitlebar(this.mBool,this.mObject);//2个参数:第一个参数是是否折叠(可以跟折叠按钮字段Foldout一样,用返回的bool值加个判断,通过自定义属性把目标对象的属性搬到被折叠的这里),第二个参数是显示的目标对象
        }
    }
}

到了这里,关于Unity插件开发笔记IMGUI-持续记录中的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包