想达到编辑器扩展的目的,需要给自己写的扩展函数一个入口.这里主要介绍一下编辑器入口常用的一些方法.
此文章内容主要来源UnityManual,与自己测试,如有错误请留言, 附官网链接Unity官方文档
MenuItem
使用方法:
在脚本中添加一个静态方法,在此静态方法上添加上如下特性即可实现函数调用
[MenuItem(string itemName, bool isValidateFunction , int priority )]参数介绍:
- itemName:这里填入的是菜单需要出现在哪里.如 Tools/myTool 则会在unity的工具导航栏处出现下图菜单.
[MenuItem("Tools/myTool")] static void Method() { }
- isValidateFunction 这里填入true或者是false 来表征修饰的函数是否是一个验证函数.请先记住这个变量,具体作用下面会介绍(默认false)
- priority 优先级标识.接收-int.MaxValue 到 int.MaxVale,觉得不同菜单显示的上下顺序,优先级标识越小越靠上.同时优先级标识相差11及以上时,将会自动以横线分割开.如下图所以,myTool1的优先级设置为1,myTool2的优先级设置为12
应用场景
- 扩展工具栏
参数说明时已经可以做到最简单的工具栏扩展,不再赘述 扩展Hierarchy面板中右键菜单栏
- 需要说明的是,Hierarchy面板右键里的菜单,是先加入了一些默认的操作,比如复制删除等,然后截取了工具栏中GameObject/菜单里的一部分(第一个横线分开之前).所以只需要把我们的菜单添加进GameObject这第一个部分里面,就可以自动被截取进Hierarchy右键菜单栏中.
如果我们想把自己的菜单加进GameObject里,那么首先需要知道GameObject第一层所处的优先级阶段,下面的图可以很好的说明它的跨度.并且我们可以看出.无论优先级多么小,都无法排在SelectPrefab之前,同时被截取的最大优先级为49.
[MenuItem("GameObject/priority -int.MaxValue", false, -int.MaxValue)]
static void Test100000() {}
[MenuItem("GameObject/priority 0",false,0)]
static void Test6() {}
[MenuItem("GameObject/priority 10", false, 10)]
static void Test7(){}
[MenuItem("GameObject/priority 49", false, 49)]
static void Test10() {}
[MenuItem("GameObject/priority 50", false, 50)]
static void Test11(){ }
所以我们把自己写的菜单路径设置成GameObject/itemName,同时优先级设置在-int.MaxValue 和 49 之间,就可以实现层级面板右键的扩展.
扩展Project视图下的右键菜单
在Project视图下的右键菜单和工具栏中Assets/下的菜单完全一样.所以只需要简单的把itemName写成 Assets/xxx 就可以了,如果需要二级菜单,需要多个/拼接路径.
扩展Inspector右键菜单(分为组件菜单和字段菜单)
- 打开组件菜单和右键菜单的方式很简单,随便点开一个组件,右键单击组件名,即可弹出组件菜单(或者点击最右面的小齿轮),右键单机变量名,则会弹出变量菜单.
- 添加组件菜单的方式有两种,第一种是使用MenuItem特性,要求填写的itemName为 CONTEXT/组件名/菜单名.下图照搬UnityManual里的示例
[MenuItem("CONTEXT/Transform/Do Something")]
static void DoSomething(MenuCommand command){}
- 添加变量菜单的方法请看下一个特性
ContextMenu
- 扩展工具栏
使用方法:
- 在创建的继承自MonoBehaviour的脚本的方法前添加如下特性.即可添加脚本菜单,当菜单被点击时,如果满足条件即可执行特性修饰的方法.
[ContextMenu(string itemName,bool isValidateFunction , int priority )] - 在创建的继承自MonoBehaviour的脚本的字段前添加如下特性,即可添加字段菜单,当菜单被点击时,会通过第二个参数名调用对应方法
[ContextMenuItem(string itemName,string functionName)]
- 在创建的继承自MonoBehaviour的脚本的方法前添加如下特性.即可添加脚本菜单,当菜单被点击时,如果满足条件即可执行特性修饰的方法.
参数介绍:
- itemName 菜单名(路径)
- isValidateFunction 是否是验证函数,同样这个参数留待最后介绍
* priority 优先级,和MenuItem参数用法一样
- functionName 当菜单被点击时调用的方法名. 仔细观察 扩展Inspector右键菜单(分为组件菜单和字段菜单)模块介绍的方法,可以看到函数中有一个MenuCommand 参数传递进来.这个参数内包含里当前选中的组件对象.command.context.而这个functionName正是调用 command.context.SendMessage()方法的参数.
应用场景
创建一个脚本,名为Test 并且将如下代码写在Test脚本中.然后随便更改一个time的值
public bool log = false;
[ContextMenuItem(“call”,”Floattest”)]
public float time = 0;
void Floattest() {time = 0; }右键点击time属性,出现字段菜单,点击call,点击前点击后的显示图如下
isValidateFunction
介绍这个参数前需要先抛出来一个问题,随便点击一个系统自带的下来菜单,应该会看到有些菜单选项是黑色的,有些菜单选项是灰色的.这两个颜色标记了这个菜单选项是否可用,可用的话点击则会调用函数,执行某些操作,不可用的话点击不会有任何效果.系统是怎么做到这些的呢?没错,就是利用了这个参数
isValidateFunction 表示是否是验证函数.可以看出凡是带这个参数的特性必然都是修饰方法的.之前的认识都是加了对应特性的方法在菜单被点击时会调用,但是实际上调用的只是isValidateFunction为false的函数.如果isValidateFunction为true,那么这个方法将不再是点击时被调用,而是菜单显示时就调用.
isValidateFunction为true的特性修饰 有bool类型返回值的方法,这个返回值的含义就是当前同名菜单是否可以使用
做个简单的尝试
[MenuItem("GameObject/priority 49", false, 49)]
static void Test10() { Debug.LogError(123); }
[MenuItem("GameObject/priority 49", true)]
static bool Test11() { return false; }
分别将Test11中的返回值改成true和false.并且分别点击 GameObject/priority 49 菜单,第一个可以打印123,第二次按钮直接变灰无法点击.说明了”验证函数”的含义,证实表征此菜单可否使用.
但是在Hirearchy的右键面板里并没有变灰,点击后依然没有打印.说明确实验证无法使用菜单,但没变灰的原因,估计是Unity的bug,总结这些东西时使用的版本是5.5.0.
函数入口常用的这些暂时总结到这里.至于像编辑器初始化和脚本初始化时调用等入口之后再总结.