插件特点,无需运行可进行编译。
分为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动画引用。文章来源:https://www.toymoban.com/news/detail-794786.html
(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模板网!