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

时间:2023-12-10 23:48:32

Unity编辑器扩展教程


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

Chinar坚持将简单的生活方式,带给世人!

(拥有更好的阅读体验 —— 高分辨率用户请根据需求调整网页缩放比例)


Brief Introduction —— 简介

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

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

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

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

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

功能键、Inspector面板、Game视窗等等都是编辑器的功能



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

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

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

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

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

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


Create MenuItem —— 创建菜单项


主要使用:静态方法

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


1

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

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

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

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

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

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

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

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

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


2

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

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

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

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

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

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


3

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

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

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

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”

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


4

- - Menu grouping —— 菜单分组

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

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

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

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

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

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”

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


5

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

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

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



验证函数 isValidateFunction 值为 true 时,此验证函数下的函数方法,会在菜单函数之前调用

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

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

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

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

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

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 会有生成一个 删除物体 的菜单项

如果选了物体,按钮可用

否则不可用

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


6

- - Shortcuts —— 快捷键

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

静态方法 MenuItem (itemName : string)



参数 itemName 为字符串,表示菜单项。+ 空格 + _O)就表示快捷键设为 O 键,不区分大小写

参数 itemName 为字符串,表示菜单项。+ 空格 + %l)就表示组合键设为 Ctrl+L 键,不区分大小写

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

组合键: % : Ctrl

组合键: # : Shift

组合键: & : Altl

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

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 ,即可打印 “所选物体的名字”:

如果选择多个,默认打印第一个(根据自己代码来判定,如有需要可自己写)

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


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


主要使用:静态方法

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


1

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

静态方法 MenuItem (itemName : string)



参数 itemName 为字符串,表示菜单项。

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

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

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

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

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,回退操作

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


2

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

静态方法 MenuItem (itemName : string)



参数 itemName 为字符串,表示菜单项。

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

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

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

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

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,完成回退

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


3

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

ContextMenu 与 ContextMenuItem 均继承自: MonoBehaviour

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

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

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

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

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

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”

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


END

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


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


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