Unity编辑器扩展
Unity窗口扩展
菜单栏添加方法
基础结构
在Unity的菜单栏中添加一个可执行方法,并指定路径。效果如图:

using UnityEditor;//引用编辑器命名空间
using UnityEngine;
public class Tools
{
[MenuItem("Tools/Test")]//引用特性,并指定路径,使Unity菜单栏上能出现对应的选项菜单
static void Test()//执行方法必须是静态的
{
Debug.Log("Test~");
}
}
MenuItem特性
MenuItem
第一个参数为路径,第二个参数是否使验证函数,第三个参数优先层级(默认层级为1000)
优先层级可以设置排序顺序,当两个方法优先级相差大于10时Unity会对其进行分类(在菜单中添加横杠)

//MenuItem第一个参数为路径,第二个参数是否使验证函数,第三个参数优先层级(默认层级为1000)
[MenuItem("Tools/Test1", false, 0)]//引用特性,并指定路径,使Unity菜单栏上能出现对应的选项菜单
static void Test1()//执行方法必须是静态的
{
Debug.Log("Test~");
}
[MenuItem("Tools/Test2", false, 5)]
static void Test2() { }
[MenuItem("Tools/Test3", false, 16)]
static void Test3() { }
右击选项
-
在Project面板中添加右击选项Test4
[MenuItem("Assets/Test4")] static void Test4() { }
-
在Hierarchy面板中添加右击选项Test5
[MenuItem("GameObject/Test5",false,10)]
static void Test5() { }
-
在组件上添加右击选项Test6
[MenuItem("CONTEXT/Transform/Test6")]// CONTEXT 组件名 按钮名
static void Test6(MenuCommand cmd)//MenuCommand 是当前正在操作的组件,不需要赋值,Unity会自动找到该组件
{
//需要将MenuCommand进行强制转型,转换成操作的组件
//需要注意转型对象命名空间,命名空间错误会导致转型不成功
Transform transform = cmd.context as Transform;
transform.position = Vector3.zero;
}
选择对象并删除
[MenuItem("Tools/Test7", false, 100)]
static void Test7()
{
//Selection.objects返回当前选中的目标对象
foreach (var item in Selection.objects)
{
//编辑模式下需要使用DestroyImmediate代替Destroy操作
//GameObject.DestroyImmediate(item);
//运用Undo进行删除操作可以在Unity中撤销
Undo.DestroyObjectImmediate(item);
}
}
添加快捷键

//_=不加组合键 %=ctrl #=shift &=alt
[MenuItem("Tools/Test8 %t")]//路径后面添加空格,在添加组合键前缀符,在添加按键字母(小写)
static void Test8()
{
Debug.Log("Test8~");
}
按钮失活

//验证方法
[MenuItem("Tools/Test9", true, 10)]
static bool Test9Validate()
{
//如果没有选中对象,则Test9按键失活
if (Selection.objects.Length>0)
{
return true;
}
return false;
}
[MenuItem("Tools/Test9", false, 10)]
static void Test9() { }
组件右击选项
与前面右击选项不同的是,接下来添加的方法是直接在组件脚本中添加。
组件添加右击选项归零:

组件字段Num添加右击选项递增:

public class TestEditor : MonoBehaviour
{
[ContextMenuItem("递增","AddNum")]//该特性可以为组件的字段增加右击选项,【按钮名,执行方法名】
public int Num;
void AddNum()
{
Num++;
}
[ContextMenu("归零")]//该特性可以直接为组件增加右击选项
void SetZero()
{
Num = 0;
}
}
脚本窗口
一个简单的脚本窗口,可以实现对选中物体的TestEditor组件的Num属性修改



public class AttributeChange : ScriptableWizard//需要继承自ScriptableWizard
{
//创建对话框
[MenuItem("Tools/CreateWizard", false, 1100)]
static void CreateWizard()
{
//创建一个脚本窗口【名称,Create按钮名称,OtherButton按钮名称】(默认OtherButton不命名是不会存在的)
ScriptableWizard.DisplayWizard<AttributeChange>("修改属性面板", "Change Value","Other Btn");
}
public int ChangeNumA = 10;
const string NumA = "NumA";
private void OnEnable()
{
//读取数据
ChangeNumA= EditorPrefs.GetInt(NumA, ChangeNumA);
}
//Create按钮事件
private void OnWizardCreate()
{
//获取选中物体
GameObject[] Prefabes = Selection.gameObjects;
//创建进度条
EditorUtility.DisplayProgressBar("进度", "0/" + Prefabes.Length + "完成修改值", 0);
int count = 0;
foreach (var item in Prefabes)
{
//获取物体身上的组件
TestEditor testEditor = item.GetComponent<TestEditor>();
//撤销记录快门,之后对组件所有修改会被记录
Undo.RecordObject(testEditor, "修改数值");
testEditor.Num = ChangeNumA;
//刷新进度条
count++;
EditorUtility.DisplayProgressBar("进度", "0/" + Prefabes.Length + "完成修改值",(float)count/ Prefabes.Length);
}
//关闭进度条
EditorUtility.ClearProgressBar();
//渐变提示框
ShowNotification(new GUIContent(Prefabes.Length + "个物体值被修改了"));
}
//OtherButton与WizardCreate不同之处在于触发事件后不会关闭窗口
private void OnWizardOtherButton()
{
OnWizardCreate();
}
//当面板字段被修改和被创建时调用
private void OnWizardUpdate()
{
}
//选择对象修改时调用
private void OnSelectionChange()
{
//提示信息
helpString = null;
errorString = null;
if (Selection.gameObjects.Length>0)
{
helpString = "您当前选择了" + Selection.gameObjects.Length + "个对象";
}
else
{
errorString = "请选择至少一个对象";
}
//保存数据
EditorPrefs.SetInt(NumA, ChangeNumA);
}
}
下面总结一些关键功能
- 渐变提示框
ShowNotification(new GUIContent(Prefabes.Length + "个物体值被修改了"));
-
进度条
//创建进度条 EditorUtility.DisplayProgressBar("进度", "0/" + Prefabes.Length + "完成修改值", 0); //刷新进度条 count++; EditorUtility.DisplayProgressBar("进度", "0/" + Prefabes.Length + "完成修改值",(float)count/ Prefabes.Length); //关闭进度条 EditorUtility.ClearProgressBar();
-
提示信息
//提示信息 helpString = null; errorString = null;
-
保存/读取Unity缓存数据
public int ChangeNumA = 10; const string NumA = "NumA"; private void OnEnable() { //读取数据 ChangeNumA= EditorPrefs.GetInt(NumA, ChangeNumA); //保存数据 EditorPrefs.SetInt(NumA, ChangeNumA); }
-
撤销
//获取物体身上的组件 TestEditor testEditor = item.GetComponent<TestEditor>(); //撤销记录快门,之后对组件所有修改会被记录 Undo.RecordObject(testEditor, "修改数值");
窗口控件
-
显示文本
GUILayout.Label($"AppId:");
-
水平垂直布局
//建立水平布局 GUILayout.BeginHorizontal();
-
下拉选框
//依据string下拉选框 int selectedIndex = EditorGUILayout.Popup(this.selectedIndex, filesArray); //依据枚举下拉选框 startConfig.AppType = (AppType)EditorGUILayout.EnumPopup(startConfig.AppType);
-
滚动框
Vector2 scrollPos = GUILayout.BeginScrollView(this.scrollPos, true, true);
网友评论