MenuItem可以向主菜单和Inspector面板上下文菜单中添加菜单项。
它具有如下三个参数:
itemName
这个参数是必传的,它用于指定菜单的路径。注意使用「MenuItem」特性的方法都必须是静态方法。
[MenuItem("AdvancedEditor/01-MenuItem/Test")]
private static void Test()
{
Debug.Log("Test");
}
我们可以在路径的结尾以类似于%_q
的形式定义菜单的快捷键
[MenuItem("AdvancedEditor/01-MenuItem/Test %_q")]
private static void Test()
{
Debug.Log("Test");
}
常见的符号代表的快捷键如下
符号 | 按键 |
---|---|
% | Ctrl/Command |
# | Shift |
& | Alt |
_a、_b、…_z | A~Z |
LEFT、RIGHT、UP、DOWN | 方向键 |
F1、F2…F12 | F1~F12 |
在路径的开头添加CONTEXT
,表示这是Inspector面板上下文菜单中的菜单项。如果方法参数为MenuCommand
,则会传入当前组件
[MenuItem("CONTEXT/Rigidbody/Init")]
private static void RigidbodyInit(MenuCommand cmd)
{
var rigidbody = cmd.context as Rigidbody;
if (rigidbody != null)
Debug.Log(rigidbody.name);
}
isValidateFunction
参数标记了当前函数是否是校验函数。比如下面这个例子,DeleteValid()
被标记为了校验函数,那么与其菜单路径相同的非校验函数DeleteSelectedItem()
,就只有在DeleteValid()
返回true时才能点击。
///
/// 添加菜单栏按钮
///
[MenuItem("AdvancedEditor/01-MenuItem/Delete Selected Item %_d",false,1)]
private static void DeleteSelectedItem()
{
Debug.Log("DeleteSelectedItem");
foreach (var obj in Selection.objects)
{
// 记录删除操作,允许撤销
Undo.DestroyObjectImmediate(obj);
}
}
///
/// 校验方法
///
[MenuItem("AdvancedEditor/01-MenuItem/Delete Selected Item %_d",true,1)]
private static bool DeleteValid()
{
if (Selection.objects.Length > 0)
return true;
return false;
}
最后一个参数priority
,顾名思义就是决定了菜单项在菜单中的位置。如果没有显式指定的话,默认值为1000。另外,如果想让菜单项之间出现上图中的横线,需要相邻两个菜单项的priority
相差10以上。
ContextMenu
用来给组件的右键菜单增加菜单选项
ContextMenuItem
用来给属性的右键菜单增加菜单选项
这两个特性属于UnityEngine
命名空间下,一般在继承了MonoBehaviour
类中使用,用来给自定义组件添加右键菜单选项。
ContextMenu
的用法如下
///
/// 给组件添加右键菜单
///
[ContextMenu("Do Something")]
private void DoSomething()
{
Debug.Log("Do Something");
}
ContextMenuItem
的用法如下
///
/// 给属性添加右键菜单
///
[ContextMenuItem("Health","HealthDescription")]
public float Health;
private void HealthDescription()
{
Debug.Log("生命值");
}
自定义对话框实现起来非常简单,只需要让我们写的脚本继承ScriptableWizard
类,然后通过调用DisplayWizard()
方法即可将对话框展示出来。脚本中的字段会显示在对话框中。下面我们来实现一个简单的自定义对话框
public class CustomWizard : ScriptableWizard
{
[MenuItem("AdvancedEditor/02-CustomWizard/CustomWizard", false, 2)]
private static void ShowCustomWizard()
{
DisplayWizard<CustomWizard>("自定义对话框");
}
public float Health = 10f;
public float Speed = 20f;
}
可以看到生成的对话框的右下角是有一个按钮的。这个按钮当然也可以自定义名称和点击事件。按钮的名称可以在DisplayWizard()
方法的第二个参数中传入,点击事件可以通过实现OnWizardCreate()
事件函数传入
[MenuItem("AdvancedEditor/02-CustomWizard/CustomWizard", false, 2)]
private static void ShowCustomWizard()
{
DisplayWizard<CustomWizard>("自定义对话框","这是一个按钮");
}
private void OnWizardCreate()
{
Debug.Log("点击了按钮");
}
我们还可以再添加一个按钮(最多两个按钮)。只需要在DisplayWizard()
方法的第三个参数中传入按钮名称,并实现OnWizardOtherButton()
事件函数即可
[MenuItem("AdvancedEditor/02-CustomWizard/CustomWizard", false, 2)]
private static void ShowCustomWizard()
{
DisplayWizard<CustomWizard>("自定义对话框","这是一个按钮","这是另一个按钮");
}
private void OnWizardOtherButton()
{
Debug.Log("点击了另一个按钮");
}
ScriptableWizard
内置的两个成员helpString
、errorString
可以在对话框中展示提示信息和错误信息,用法如下
// 对话框开启、字段变更时调用
private void OnWizardUpdate()
{
helpString = "";
errorString = "";
if (Selection.gameObjects.Length == 0)
{
errorString = "您未选择物体";
}
else
{
helpString = $"您选择了{Selection.gameObjects.Length}个物体";
}
}
// 选中的元素发生变更时调用
private void OnSelectionChange()
{
OnWizardUpdate();
}
也可以使用EditorWindow
类下的ShowNotification()
方法显示提示信息
private void OnWizardOtherButton()
{
ShowNotification(new GUIContent("点击了另一个按钮"));
}
最后,如果我们想创建类似于「Inspector」面板这种系统内置的窗口,可以让脚本继承EditorWindow
类来实现,然后通过OnGUI
绘制其中的元素。
public class CustomEditorWindow : EditorWindow
{
[MenuItem("AdvancedEditor/02-CustomWizard/CustomEditorWindow", false, 3)]
private static void ShowWindow()
{
var window = GetWindow<CustomEditorWindow>();
window.Show();
}
private string _name = "";
private void OnGUI()
{
GUILayout.Label("名称");
_name = GUILayout.TextField(_name);
if (GUILayout.Button("创建物体"))
{
GameObject go = new GameObject(_name);
Undo.RegisterCreatedObjectUndo(go,"Create GameObject");
}
}
}