您的位置:首页 >滚动 >

【Unity3D实用技巧·一】自定义快捷键

2023-08-09 00:48:29    来源:哔哩哔哩

如果说一定要选出世界上最喜欢用快捷键的群体的话,那么一定是程序员了。

——龙儿

一方面为了激励自己保持学习,并将学习当中碰到的一些问题记录下来,另一方面也是感叹Unity中文互联网资料还是不够齐全繁多,有时候一个简单的问题要查询许久,并且查到的也经常是东一榔头西一棒子、不够系统化,有些资料甚至语焉不详,因此自然模仿无数前辈萌生了自己写Blog的想法,这便是《Unity3D实用技巧》。


【资料图】

本栏目中我计划结合自身的实际工作、学习经历不断分享一些不复杂却实用的,能有效提高U3D工程效率的技巧。

正如我一开始所说的,似乎习惯用键盘工作的人总是恨不得全面抛弃鼠标,最好工作时手完全不要离开键盘,其中程序员一定是佼佼者,毕竟思路到一半被烦人的移动鼠标打断总是痛苦的。而使用U3D过程中,自然而然的针对一些常用的需求,比如坐标归零、层级排序、切换正交视图等,Unity居然没有准备快捷键,真让人恼火,于是第一期就是分享如何定义自己的快捷键。

实际上自定义快捷键的本质是通过快捷键调用Unity编辑器菜单中的一个菜单项,而编辑器的菜单项是高度可自定义的,也就是说,我们可以编写一些自己的功能,自己的逻辑,并随时调用它。

简单的介绍过后,我们先直接以一个实例开始!

快捷键与"Hello!World!"

我们在Unity工程中创建好上面的脚本,此时在编辑器中按下Alt+Q就可以看到我们的控制台中已经打印出了"Hello!World!"字样。

截止于此,我们就可以快速的打印"Hello!World"了。

刚接触Unity的人可以先按照上面的步骤简单实践一下,加深理解。

进阶!实践!与[MenuItem()]标签

下面先直接贴一段用于将单个选中物体transfrom重置的代码,然后结合代码我们进一步深入了解MeunItem是什么?能干什么?为什么?

这样我们就简单的实现了通过快捷键“Alt+r”使选中的物体transform置零的操作。他在表现上和我们手动在transform组件上点击Reset是一致的。

相似的我们实际上可以在方法体中写任何的自定义内容。

但是有一点需要注意,我们自定义的快捷键不能和Unity已经有的快捷键冲突,那么如何查看unity内置的快捷键呢?

我们可以在Edit的Shortcuts中打开unity的快捷键窗口,同时也可以在这里设置内置的快捷键命令。

另外这里是一些常用的自定义快捷键:

ctrl %

shift #

alt &

单个字母快捷键前缀 _

如果只是想了解如何在Unity中自定义快捷键那么到这里其实已经介绍完80%的内容了,剩下的细枝末节大家可以在网上检索Unity编辑器扩展自行查阅更多的相关内容。

我们重点来关注一下背后的原理,为什么这样做就可以实现自定义快捷键了呢?从原理层面,我们到底做了什么?

底层一点的层面讲,Unity是通过“反射”来遍历、检索、调用对应的函数来实现功能的,具体的机制我们可以搜索“Unity 反射”相关的字样进一步了解,我们的[MenuItem()]标签原理也是类似的,通过给自定义静态方法加标签,我们让编辑器自动生成了一个菜单项,并在触发这个菜单项时,回调对应的方法。

PS:针对Unity反射机制与标签的原理的解析,这里推荐一下CSDN上,漫漫无期老师和用c#写unity的杰宝老师以及宿春磊Charles老师的文章,我们可以从中管中窥豹得以照见Unity的运行机理。

因为不是此处讨论的重点,所以不再过多深入解析,而是我们直接来看我们实用的特性标签[MenuItem()]

面对不了解的API,我们首先查询一下手册,查询Unity官方手册可以看到如下的解释

直接看重点,用于向主菜单和上下文检视菜单创建菜单项,仅可对静态函数使用,与我们上文的实践相符。这说明了该标签的作用确实是创建菜单项,我们回头看看上面实例在工程中的体现。

确实创建了两个菜单项,接下来我们删除掉实例中的快捷键,并手动点击它试试。

实践证明通过快捷键或者手动点击得到的结果完全一致。

此时可能有些写过编辑器脚本的朋友也想起了,我们创建自定义窗口时,也是通过类似的方法创建的,我们也可以在此试验一下。

点击创建出来的菜单项后,得到了这样的结果。

结果很好的符合了我们的预期,这个例子意味着我们可以通过类似的方式来DIY自己的U3DEditor。

继续回头看MenuItem标签,我们发现标签其实是有三个重载的,除了除了菜单项的路径,我们还可以显式的指定他是否是验证函数,指定他的优先级。

官方手册一贯的不说人话,我们直接上实例来说明第二个参数的用途。

发现只创建了名为TestFalse的菜单项,这是怎么回事呢?我们直接查看一下MenuITem的源码。

翻译一下:

//   isValidateFunction: 

//     如果 isValidateFunction 为 true,这是一个验证函数,在与相同 itemName 的菜单函数被调用之前执行。

似乎暗示了我们需要一个相同名称的菜单项,那么我们接着实践一下。

此时创建了菜单项,但他无法点击,永远是Disabled状态,我们回头继续查阅一下Unity的手册。

也就是说,[MenuItem()]特性要求我们的验证函数返回一个Bool值,如果这个值是true则启用我们的菜单项,反之不启用,我们实践一下。

至于最后一个优先级,我们直接看一个例子就能了解清楚。

说明了两件事:1、优先级越小越靠上 2、当优先级间隔大于10时,会分组

到此,我们队[MenuItem()]的了解和应用也说得七七八八了,只剩下一些小问题写在最后。

番外1:验证函数的调用问题

上面虽然说了验证函数,但是较真的人肯定会好奇,我们究竟是什么时候调用验证函数的呢?不妨测试一下。

这样一来,我们只需要观察Unity在什么时候会打印消息就可以知道了。

只是创建新物体,当数量为5的时候,并未调用验证函数。

依然没调用。

数量到了7,此时毫无疑问验证函数的结果从false变为了true,但是他依然没有调用。

我们尝试看一下菜单项。

我们发现,当我们“试图调用被验证函数时”,验证函数被调用了,无论我们是否实际调用了被验证函数。有些类似对象的构造方法,当我们实例化类时,调用了类的构造方法,无论我们是否实际使用了这个类的对象。

番外2:物体右键菜单与Assets窗口的右键菜单

1、只需要将路径设为“GameObject/实际菜单项名称”,并且优先级小于等于49就可以添加右键菜单了

2、只需要将路径设为“Assets/自定义菜单_Assets”,就可以添加Assets的右键菜单了,下面是示例

结语:

写的有些啰嗦,但是需要了解的和一些拓展应用应该都介绍到位了,希望能有机会帮到一些人;完整的代码因为懒就不放了,实际起作用的代码都在文中了,有需要的自行取用即可。

转载自便,标不标出处都可以。

关键词:

相关阅读

精彩放送