Unity编辑器扩展-菜单项

    xiaoxiao2021-04-16  34

    Unity编辑器允许你去添加像内置菜单一样外观和行为的自定义菜单。自定义菜单对于那些经常使用的功能提供一种能从编辑器直接访问的便捷方式。在这一课程中我将对每个描述的主题提供真实的使用示例,用于说明在unity中的菜单项是如何创建和使用的。

    添加菜单项

    为了要在顶层工具栏中创建一个新的菜单项,你必须去创建一个编辑器脚本(在项目Editor目录下的一个脚本)。此菜单项需要是一个静态的方法且必须使用MenuItem属性来标识。例如,去添加一个你的团队和公司经常使用的命令到“Tools”菜单。  下面的示例,在Tools菜单下添加了一个“Clear PlayerPrefs”选项:

    using UnityEngine; using UnityEditor; public class MenuItems { [MenuItem("Tools/ClearPlayerPrefs")] private static void NewMenuOption() { PlayerPrefs.DeleteAll(); } } 1234567891011 1234567891011

    这段代码创建了一个叫“Tools”的菜单,并在下面放置了一个叫“Clear PlayerPrefs”的菜单项。    当然我们也可以在一个现成的菜单项下面创建新的菜单项(例如:在“Windows”菜单下),也可以创建多级子菜单便于更好的组织菜单项目:

    using UnityEngine; using UnityEditor; public class MenuItemsExample { // Add a new menu item under an existing menu [MenuItem("Window/New Option")] private static void NewMenuOption() { } // Add a menu item with multiple levels of nesting [MenuItem("Tools/SubMenu/Option")] private static void NewNestedOption() { } } 12345678910111213141516171819 12345678910111213141516171819

    上面的代码产生的结果如下: 

    快捷键

    为了使超级用户和喜欢使用键盘的用户工作的更快捷,我们可以为新的菜单项关联一个快捷键-使用快捷键的组合将自动的启动他们菜单项。  下面是被指定的键(它们也可以组合起来使用):

    %-CTRL 在Windows / CMD在OSX# -Shift& -AltLEFT/RIGHT/UP/DOWN-光标键F1…F12HOME,END,PGUP,PDDN

    字母键不是key-sequence的一部分,要让字母键被添加到key-sequence中必须在前面加上下划线(例如:_g对应于快捷键”G”)。  快捷键的组合被添加在菜单项的路径后面,并以一个空格分隔。如下显示的示例:

    // Add a new menu item with hotkey CTRL-SHIFT-A [MenuItem("Tools/New Option %#a")] private static void NewMenuOption() { } // Add a new menu item with hotkey CTRL-G [MenuItem("Tools/Item %g")] private static void NewNestedOption() { } // Add a new menu item with hotkey G [MenuItem("Tools/Item2 _g")] private static void NewOptionWithHotkey() { } 12345678910111213141516171819 12345678910111213141516171819

    使用了快捷键的菜单项将显示用于启动它们的快捷键,示例如下:    注意:这里没有验证重复的快捷键,如果定义了多个相同的快捷键,那么也只有一个菜单项被调用。

    特殊路径

    显示,传递到MenuItem属性上的路径确定了新的菜单项将被放置在哪个顶层菜单下。Unity有些特殊的路径作用于上下文菜单(通过右键访问的菜单):

    Assets -菜单项将被显示在“Assets”菜单下,同时也显示在右键单击项目视图时弹出的菜单中。Asset/Create - 菜单项将被列出在,当你在项目视图中单了右键菜单里的“Create”子菜单中(当你创建了能够添加项目的新类型时,此功能是是非常有用的)。CONTEXT/ComponentName - 菜单项将出现在给定组件的上下文菜单(右键单击显示的菜单)中。

    下面显示了一些如何使用特殊路径的示例:

    // Add a new menu item that is accessed by right-clicking on an asset in the project view [MenuItem("Assets/Load Additive Scene")] private static void LoadAdditiveScene() { var selected = Selection.activeObject; EditorApplication.OpenSceneAdditive(AssetDatabase.GetAssetPath(selected)); } // Adding a new menu item under Assets/Create [MenuItem("Assets/Create/Add Configuration")] private static void AddConfig() { // Create and add a new ScriptableObject for storing configuration } // Add a new menu item that is accessed by right-clicking inside the RigidBody component [MenuItem("CONTEXT/Rigidbody/New Option")] private static void NewOpenForRigidBody() { } 1234567891011121314151617181920212223 1234567891011121314151617181920212223

    上面代码片段产生的结果如下图:

    有效性验证

    有些菜单项仅在指定的情况下才可用,否则就应该被禁用。根据它的上下文添加一个验证方法来启用/禁用一个菜单项。  验证方法是一个静态的,并使用MenuItem属性标记的一个方法,且此属性传递true作为一个验证参数。  这个验证方法应该和菜单的命令方法有相同的路径,并且要有一个boolean的返回值,用以确认菜单是否被激活或者禁用。  例如,验证方法能够被用于在项目视图里一个纹理上的右键菜单:

    [MenuItem("Assets/ProcessTexture")] private static void DoSomethingWithTexture() { } // Note that we pass the same path, and also pass "true" to the second argument. [MenuItem("Assets/ProcessTexture", true)] private static bool NewMenuOptionValidation() { // This returns true when the selected object is a Texture2D (the menu item will be disabled otherwise). return Selection.activeObject.GetType() == typeof(Texture2D); } 123456789101112 123456789101112

    当在非任意纹理上单击右键时,此菜单项将会被显示成灰色: 

    控制菜单的优先顺序

    优先级是个被赋值到菜单项一个数字(传递给MenuItemde的第3个参数),它控制了菜单的显示顺序。  菜单项也能够自动的分组,每50个一个组:

    [MenuItem("NewMenu/Option1", false, 1)] private static void NewMenuOption() { } [MenuItem("NewMenu/Option2", false, 2)] private static void NewMenuOption2() { } [MenuItem("NewMenu/Option3", false, 3)] private static void NewMenuOption3() { } [MenuItem("NewMenu/Option4", false, 51)] private static void NewMenuOption4() { } [MenuItem("NewMenu/Option5", false, 52)] private static void NewMenuOption5() { } 123456789101112131415161718192021222324 123456789101112131415161718192021222324

    上面的代码示例显示如下的结构,菜单项被分为了两个组:

    其他相关的类

    下面列出了对于添加菜单项一些相关的类。

    当添加一个新的菜单项到Inspector中(使用 “CONTEXT/Component”),有时候获取一个真实组件的引用也是有必要的(例如:修改它的数据)。  这可以通过给新菜单项的静态方法添加一个MenuCommand参数。

    [MenuItem("CONTEXT/RigidBody/New Option")] private static void NewMenuOption(MenuCommand menuCommand) { // The RigidBody component can be extracted from the menu command using the context field. var rigid = menuCommand.context as RigidBody; } 123456 123456

    ContextMenu

    这个属性允许你去定义上下文菜单。它和使用MenuItem并以“CONTEXT/…”作为路径定义菜单项一样。  这个属性不同的是,你能给指定的组件定义默认的上下文菜单项,然而使用MeneItem只是为了扩展现有的组件菜单,比如引擎默认的组件。  示例-组件将显示一个用于清除数据的菜单项:

    public class NameBehaviour : MonoBehaviour { public string Name; [ContextMenu("Reset Name")] private static void ResetName() { Name = string.Empty; } } 12345678910 12345678910

    ContextMenuItem

    这个属性被添加到组件类的字段上,上面显示了ContextMenu属性在组件上下文菜单中添加了一个菜单项,然后ContextMenuItem属性将在字段的上下文菜单中添加一个菜单项。  由于这个属性被添加到了一个字段上没有方法,所有它接受两个参数:一个用于显示菜单项的名字,一个用于指定一个当菜单被选中时要调用的实例方法。  实例-添加一个随机初始化字段的方法:

    public class NameBehaviour : MonoBehaviour { [ContextMenuItem("Randomize Name", "Randomize")] public string Name; private void Randomize() { Name = "Some Random Name"; } } 12345678910 12345678910

    上面代码的结果显示了当在字段上单击右键时弹出的菜单项:

    AddComponentMenu

    此属性允许你去放置脚本到“Component”菜单下的任意位置,而不只是在“Component->Scripts”菜单下。你能使用它去更好的组织你的脚本。这个属性能够改善添加脚本的工作流程。重要提示:你需要重启才生效。

    using UnityEngine; [AddComponentMenu("Transform/Follow Transform")] public class FollowTransform : MonoBehaviour { } 123456 123456

    GenericMenu

    GenericMenu让你可以创建一个自定义的上下文菜单和下拉菜单,下面这个示例打开一个带有绿色区域的窗口,在绿色区域上单击右键将显示一个菜单,当触发了菜单中选中的项时将触发一个回调。

    using UnityEngine; using UnityEditor; using System.Collections; // This example shows how to create a context menu inside a custom EditorWindow. // context-click the green area to show the menu public class GenericMenuExample : EditorWindow { [MenuItem("Example/Open Window")] static void Init() { var window = GetWindow<GenericMenuExample>(); window.position = new Rect(50, 50, 250, 60); window.Show(); } void Callback(object obj) { Debug.Log("Selected: " + obj); } void OnGUI() { Event currentEvent = Event.current; Rect contextRect = new Rect(10, 10, 100, 100); EditorGUI.DrawRect(contextRect, Color.green); if (currentEvent.type == EventType.ContextClick) { Vector2 mousePos = currentEvent.mousePosition; if (contextRect.Contains(mousePos)) { // Now create the menu, add items and show it GenericMenu menu = new GenericMenu(); menu.AddItem(new GUIContent("MenuItem1"), false, Callback, "item 1"); menu.AddItem(new GUIContent("MenuItem2"), false, Callback, "item 2"); menu.AddSeparator(""); menu.AddItem(new GUIContent("SubMenu/MenuItem3"), false, Callback, "item 3"); menu.ShowAsContext(); currentEvent.Use(); } } } } 12345678910111213141516171819202122232425262728293031323334353637383940414243444546 12345678910111213141516171819202122232425262728293031323334353637383940414243444546

    总结

    这篇文章说展示的,在Unity编辑器中去扩展一个菜单项是非常简单的。  在编辑器中为常用功能建立菜单项。可以为规范团队开发并且能够节约很多时间。

    原文地址

    http://unity3d.com/cn/learn/tutorials/modules/intermediate/editor/menu-items

    http://docs.unity3d.com/ScriptReference/GenericMenu.html

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

    最新回复(0)