Unity 3D编辑器扩展介绍、教程(一) —— 创建菜单项

xiaoxiao2021-02-28  73

Unity编辑器扩展教程


本文提供全流程,中文翻译。Chinar坚持将简单的生活方式,带给世人!(拥有更好的阅读体验 —— 高分辨率用户请根据需求调整网页缩放比例)


一 Brief Introduction —— 简介 二 Create MenuItem —— 创建菜单项 1- - Create Level 1 Menu —— 创建一级菜单2- - Create Level 2 Menu —— 创建二级菜单3- - Create Level 2 Menu in System Menu —— 在系统菜单中创建二级菜单4- - Menu grouping —— 菜单分组5- - Menu display and hide. —— 菜单的显示和隐藏6- - Shortcuts —— 快捷键 三 Create MenuItem for the Component —— 创建组件上的菜单项 1- - Script Component —— 在脚本组件上添加菜单项2- - Syetem Component —— 在系统组件上添加菜单项3- - ContextMenu —— 组件菜单的用法


Brief Introduction —— 简介

我们在做工程的时候,需要对数据进行操作。

为节省时间,会使用一些快捷键,菜单栏上的功能、或是右键菜单

这些便捷的功能,都是Unity官方为了方便我们对所需数据进行操作。

对Unity编辑进行了一些封装处理,简化数据操作流程,封装为一个按钮/一个窗口/窗口功能。

这些诸如此类的功能就是编辑器的扩展,和封装

功能键、Inspector面板、Game视窗等等都是编辑器的功能 注意:编辑器类脚本,必须放在 Assets/Editor 资源目录中

此文件夹下的脚本只对编辑器进行操作。最后资源打包,Editor文件夹下的所有资源都不会被打包到工程中

如果没有此文件夹,需自行创建:在Project视窗下,右键Create - - Folder


Create MenuItem —— 创建菜单项


主要使用:静态方法

MenuItem (itemName : string, isValidateFunction : bool, priority : int)


1- - Create Level 1 Menu —— 创建一级菜单

在菜单栏上创建一个菜单项,并创建一个一级菜单按钮

注意:编辑器类脚本,必须放在 Assets/Editor 资源目录中

此文件夹下的脚本只对编辑器进行操作。最后资源打包,Editor文件夹下的所有资源都不会被打包到工程中

如果没有此文件夹,需自行创建:在Project视窗下,右键Create - - Folder

using UnityEditor; //引用Unity编辑器命名空间 using UnityEngine; //引用Unity引擎命名空间 /// <summary> /// 创建一个脚本工具类 /// </summary> public class Tools//脚本无需继承自MonoBehaviour { /// <summary> /// 创建新的菜单项 /// </summary> /// //在菜单栏中创建一个 我的工具 菜单项目,并生成一个 “一级选项” 的按钮:需要对应一个静态方法(名字最好保持一致,不一致也可),方法体自由定义 [MenuItem("我的工具/一级选项")] //菜单项(“菜单栏名称/子类名称”)—— 经过测试可为中文 static void 一级选项() //必须设置成静态方法 —— 经过测试,亦可为中文 { Debug.Log(111); } }

会有生成一个 一级选项 的按钮,点击后打印“111”


2- - Create Level 2 Menu —— 创建二级菜单

在菜单栏上创建一个菜单项,并创建一个二级菜单按钮

using UnityEditor; //引用Unity编辑器命名空间 using UnityEngine; //引用Unity引擎命名空间 /// <summary> /// 创建一个脚本工具类 /// </summary> public class Tools//脚本无需继承自MonoBehaviour { /// <summary> /// 创建二级菜单项 /// </summary> /// //在菜单栏中创建一个 我的工具 菜单项目,并生成一个 “二级选项” 的按钮:需要对应一个静态方法(名字最好保持一致,不一致也可),方法体自由定义 [MenuItem("我的工具/一级选项/二级选项")] //菜单项(“菜单栏名称/子类名称”)—— 经过测试可为中文 static void 二级选项() //必须设置成静态方法 —— 经过测试,亦可为中文 { Debug.Log(222); } }

会有生成一个 二级选项 的按钮,点击后打印“222”


3- - Create Level 2 Menu in System Menu —— 在系统菜单中创建二级菜单

在系统菜单 Edit 中创建二级菜单

using UnityEditor; //引用Unity编辑器命名空间 using UnityEngine; //引用Unity引擎命名空间 /// <summary> /// 创建一个脚本工具类 /// </summary> public class Tools//脚本无需继承自MonoBehaviour { /// <summary> /// 在系统默认的菜单项中,创建子按钮 /// </summary> /// //在系统默认菜单项 Edit 中创建按钮:(名字最好保持一致,不一致也可) [MenuItem("Edit/一级选项/二级选项2")] static void 二级选项2() { Debug.Log(333); } }

Edit 中最下方,会有生成一个 二级选项2 的按钮,点击后打印“333”


4- - Menu grouping —— 菜单分组

完成菜单的分组,例如系统中的多个菜单项分组管理

静态方法 MenuItem (itemName : string, isValidateFunction : bool, priority : int)

MenuItem (表示菜单项:就是路径名 , 验证函数 : 同名的按钮在菜单函数调用之前调用 , 优先级:用来管理菜单项的层级关系)

注意: Priority 优先级如果设置为:-1 ,那么必然是在第一个

using UnityEditor; //引用Unity编辑器命名空间 using UnityEngine; //引用Unity引擎命名空间 /// <summary> /// 创建一个脚本工具类 /// </summary> public class Tools//脚本无需继承自MonoBehaviour { /// <summary> /// 菜单分组 —— 层级10 /// </summary> /// //每个菜单栏的 priority 属性:优先级默认为1000。相差 11 可以分为另一个组。也就是大于10就另建一组 [MenuItem("按钮/功能1", false, 10)] static void 功能1() { Debug.Log("功能1"); } /// <summary> /// 菜单分组 —— 层级:如果不填,系统默认为1000,所以排序在最后 /// </summary> [MenuItem("按钮/功能2")] static void 功能2() { Debug.Log("功能2"); } /// <summary> /// 菜单分组 —— 层级:21 /// </summary> /// //与按钮1的层级10,相差11,故而分到了另一组中 [MenuItem("按钮/功能3", false, 21)] static void 功能3() { Debug.Log("功能3"); } }

菜单栏会有生成一个 功能 的菜单项,其中有:功能1/3/2。点击后分别打印“1/3/2”


5- - Menu display and hide. —— 菜单的显示和隐藏

完成菜单的显示和隐藏,有些时候菜单项是灰色,不可用状态/可用状态

静态方法 MenuItem (itemName : string, isValidateFunction : bool, priority : int) 验证函数 isValidateFunction 值为 true 时,此验证函数下的函数方法,会在菜单函数之前调用

满足条件,则按钮显示/否则隐藏

注意: Hierarchy 面板中,右键菜单是 菜单栏里 GameObject 的菜单项。

所以在 GameObject 菜单栏中创建一个按钮,并且优先级设置到第一组中,即可在 Hierarchy 的右键菜单中显示 该按钮

注意: Priority 优先级如果设置为:-1 ,那么必然是在第一个

using UnityEditor; //引用Unity编辑器命名空间 using UnityEngine; //引用Unity引擎命名空间 /// <summary> /// 创建一个脚本工具类 /// </summary> public class Tools//脚本无需继承自MonoBehaviour { /// <summary> /// 验证“删除物体”按钮的 显示/隐藏 /// </summary> [MenuItem("GameObject/删除物体", true, -1)] static bool 删除物体Alternative() { if (Selection.objects.Length > 0)//如果选择了物体 { return true;//就返回真:按钮可用 } else//否则 { return false;//返回假:按钮不可用 } } /// <summary> /// 在系统默认的菜单项 GameObject 中,创建 删除物体 按钮,优先级第一个 /// </summary> [MenuItem("GameObject/删除物体", false, -1)] static void 删除物体() { //Selection.objects 返回值是一个 Object数组,就是选中的所有物体 foreach (var o in Selection.objects) //遍历选中的所有物体 { //GameObject.DestroyImmediate(o);//直接删除,但是无法撤销 Undo.DestroyObjectImmediate(o); //直接删除,但是可以撤销(用Ctrl+z)//Immediate:直接的,立即的 } } }

菜单栏 GameObject 会有生成一个 删除物体 的菜单项

如果选了物体,按钮可用

否则不可用


6- - Shortcuts —— 快捷键

完成对菜单项目的快捷键设置

静态方法 MenuItem (itemName : string) 参数 itemName 为字符串,表示菜单项。+ 空格 + _O)就表示快捷键设为 O 键,不区分大小写 参数 itemName 为字符串,表示菜单项。+ 空格 + %l)就表示组合键设为 Ctrl+L 键,不区分大小写

注意:名字和快捷键中间必须要有空格

组合键: % : Ctrl 组合键: # : Shift 组合键: & : Altl

using UnityEditor; //引用Unity编辑器命名空间 using UnityEngine; //引用Unity引擎命名空间 /// <summary> /// 创建一个脚本工具类 /// </summary> public class Tools//脚本无需继承自MonoBehaviour { /// <summary> /// 快捷键测试 /// </summary> [MenuItem("我的工具/快捷键测试 _o")]//_o 是指定快捷键 O ,并不区分大小写 (名字和快捷键中间必须要有空格) static void 选中物体个数() { Debug.Log("快捷键"+Selection.objects.Length);//打印选中物体的个数 } /// <summary> /// 在系统默认的菜单项中,创建子按钮 /// </summary> /// % : Ctrl /// # : Shift /// & : Alt [MenuItem("我的工具/组合键测试 %l")] //%l 是指定组合键:Ctrl+L,并不区分大小写 (名字和快捷键中间必须要有空格) static void 快捷键测试() { Debug.Log("组合键"+ Selection.activeGameObject.name); //打印物体名/—— 默认打印第一个选中的物体,无论选中了几个 } }

点击键盘按钮 O ,即可打印 “选择物体的个数”

点击键盘按钮 Ctrl + L ,即可打印 “所选物体的名字”: 如果选择多个,默认打印第一个(根据自己代码来判定,如有需要可自己写)


Create MenuItem for the Component —— 创建组件上的菜单项


主要使用:静态方法

MenuCommand : Context —— 菜单命令的目标对象


1- - Script Component —— 在脚本组件上添加菜单项

静态方法 MenuItem (itemName : string) 参数 itemName 为字符串,表示菜单项。

参数 “CONTEXT/ PlayerHealth” 为 组件 路径

若想对某个(组件/脚本)进行操作,必须写上 “CONTEXT/ (组件/脚本)名

Undo.RecordObject (对象,键) 此函数用于记录对象之后的数据变化,没有则不能回退操作

using UnityEditor; //引用Unity编辑器命名空间 using UnityEngine; //引用Unity引擎命名空间 /// <summary> /// 玩家脚本上的工具 —— 测试脚本 /// </summary> public class PlayerTools { /// <summary> /// 给玩家脚本组件上添加按钮:初始化人物 /// </summary> /// //[菜单项函数(“环境(组件:想要给组件上加必须要用这个来表示路径)/所需控制组件(脚本名)/需要执行的方法名(就是按钮名)”)] [MenuItem("CONTEXT/PlayerHealth/初始化人物")] static void 初始化人物(MenuCommand command) //MenuCommand 正在操作的组件对象类 { CompleteProject.PlayerHealth player = (CompleteProject.PlayerHealth) command.context; //声明一个PlayerHealt对象 th —— 需要强转为 PlayerHealth类型 Undo.RecordObject(player, "PlayerTools_player"); //记录对象 player 之后的数据变化,用于回退 —— 记录对象(对象,键);//键的名字随意,不能重复//如果没有这句话,是不能退会之前的修改的 player.startingHealth = 100; //血量初始化到100 } }

右键点击组件 ,选择 初始化人物 : 即可完成对血量的初始化 —— Ctrl+z,回退操作


2- - Syetem Component —— 在系统组件上添加菜单项

静态方法 MenuItem (itemName : string) 参数 itemName 为字符串,表示菜单项。

参数 “CONTEXT/ Rigidbody” 为 组件 路径

若想对某个(组件/脚本)进行操作,必须写上 “CONTEXT/ (组件/脚本)名

Undo.RecordObject (对象,键) 此函数用于记录对象之后的数据变化,没有则不能回退操作

using UnityEditor; //引用Unity编辑器命名空间 using UnityEngine; //引用Unity引擎命名空间 /// <summary> /// 玩家脚本上的工具 —— 测试脚本 /// </summary> public class PlayerTools { /// <summary> /// 给系统组件 Rigidbody 上添加按钮:取消重力 /// </summary> /// <param name="command"></param> [MenuItem("CONTEXT/Rigidbody/取消重力")] static void 取消重力(MenuCommand command) { Rigidbody rig = (Rigidbody) command.context; //context是一个 (正操作/鼠标下) 的组件:返回值为Object —— 强转为需要的类型 Undo.RecordObject(rig, "PlayerTools_rig"); //记录 rig 之后的数据变化,用于回退 —— 记录对象(对象,键);//键的名字随意,不能重复//没有这句话,是不能回退,因为系统没记录 rig.mass = 0; //质量为0 rig.useGravity = false; //关闭重力 } }

右键点击刚体组件 ,选择 取消重力: 即可完成对重力的取消 —— Ctrl+z,完成回退


3- - ContextMenu —— 组件菜单的用法

ContextMenu ContextMenuItem 均继承自: MonoBehaviour

所以可以直接在 自义定脚本中使用,也就是工程脚本中直接用

[ContextMenuItem(按钮名,方法名)] 需要写在所需控制变量之上

[ContextMenu(按钮名)] 需要直接写在方法上

Undo.RecordObject (对象,键) 此函数用于记录对象之后的数据变化,没有则不能回退操作

using UnityEngine; using UnityEngine.UI; using UnityEngine.SceneManagement; /// <summary> /// 玩家健康属性脚本 /// </summary> public class PlayerHealth : MonoBehaviour { [ContextMenuItem("增加血量50", "增加血量")] //按钮名,方法//需要写在所需控制变量之上 public int startingHealth = 100; // 初始血量 /// <summary> /// 直接在脚本中设置菜单项,即可在 面板中右键显示 该按钮 /// </summary> [ContextMenu("设置属性")]//可以直接在脚本方法里写,需要直接写在方法上 void 设置属性() { Debug.Log("设置属性"); } /// <summary> /// 为变量 startingHealth 提供方法,每点击一次加 50 /// </summary> void 增加血量() { Undo.RecordObject(this, "PlayerHealth_startingHealth");//记录值的改变,用于回退//(对象,键) startingHealth += 50; } }

右键点击 PlayerHealth 脚本组件 ,即可看到按钮“设置属性”

点击 PlayerHealth 脚本组件 ,选择 startingHealth 属性,右键即可看到按钮“增加血量50”


END

本博客为非营利性个人原创,除部分有明确署名的作品外,所刊登的所有作品的著作权均为本人所拥有,本人保留所有法定权利。违者必究 对于需要复制、转载、链接和传播博客文章或内容的,请及时和本博主进行联系,留言,Email: ichinar@icloud.com 对于经本博主明确授权和许可使用文章及内容的,使用时请注明文章或内容出处并注明网址

转载请注明原文地址: https://www.6miu.com/read-2595506.html

最新回复(0)