前言
此文为UnityEditor的入门文章,在UnityEditor中我们可以很方便的使用它自带的UnityEditor类中相关的工具,实现我们工具的可视化以及修改添加部分编辑中的功能。
- 为什么需要编辑器扩展?
因为项目中可能很多时候存在重复性工作,而我们做成工具类后,可以使用代码帮我们快速的完成这些工作。 - 相较于Python书写工具,Editor有哪些优劣?
- Python工具
- (优势)但是一旦开发完成,我们可以用于任何引擎,需求只需要根据项目而定
- (劣势)需要额外的去实现可视化操作,并且调用Unity自身Api不是那么方便
- Editor工具
- (优势)可以快速的实现可视化的操作,便于调用Unity中本身的相关Api,开发效率相对高一些。
- (劣势)不是那么容易移植到其他游戏引擎中
- 建议
- 可视化要求不高,并且对Unity自身Api依赖度低的工具采用Python开发。(例如:批量修改资源名,修改meta文件中部分的内容等等)
- 相反,尽量使用引擎自身的编辑器扩展方法
- Python工具
视频学习: 基础:siki学习
源码:
官方文档:
Unity版本:2018.4.18f
开始
-
了解
Unity引擎扩展的类,都放在Editor目录下
Editor:该目录下资源都不会被打包
因此这些方法,只能在编辑器模式下有用,项目发布后是无法使用的 -
主要内容
- 菜单栏的功能添加
- 选中项Selection
- 回撤操作
- 创建独立窗口
菜单栏(MenuItem 用法)
unity manual: ScriptsApi(查询相关方法Api)
- 创建
在静态方法上加上[MenuItem("Tools/Test")] ,即可在Unity上方创建一个新的Tools选项,进入后有一个可点击按钮Test
using UnityEditor;
using UnityEngine;
public EditorExtend
{
[MenuItem("Tools/Test")]
static void Test()
{
Debug.Log("Test");
}
}
- 分类
每个[MenuItem("xxx/xxx")] 默认优先级priority是1000
可以使用[MenuItem("Tools/Test",false,1)] 修改优先级,优先级越小越在上面,其中第三个参数为优先级,第二个参数暂时可以忽略
using UnityEditor;
using UnityEngine;
public EditorExtend
{
[MenuItem("Tools/Test",false,3)]
static void Test()
{
Debug.Log("Test");
}
[MenuItem("Tools/Test2",false,2)]
static void Test2()
{
Debug.Log("Test2");
}
[MenuItem("Tools/Test3",false,15)]
static void Test3()
{
Debug.Log("Test3");
}
[MenuItem("Tools/Test4",false,4)]
static void Test4()
{
Debug.Log("Test4");
}
}
在Tools选项卡中,会将 Test,Test2,Test4归为一类,并且Test2最上,Test中间,Test4最下面;然后Test3 分为一类。
优先级相差11以上为一类,即添加横线
- 修改
- 如果我们现在Unity编辑原本的GameObject选项卡中添加一项
[MenuItem("GameObject/MyTool",false,10)] - 在Asset选项卡中添加一项
[MenuItem("Assets/MyTool1",false,1000)]
- 如果我们现在Unity编辑原本的GameObject选项卡中添加一项
同时我们原本在Project中“右键”会有弹窗,其中也会添加上我们的MyTool1的选项,而在GameObject选项卡中,将优先级设置为10左右,也能够在Hierarchy面板中右键弹窗显示相应按钮"MyTool"
具体案例的使用
官方项目:survial shooter
我们的MenuItem还有在Inspector中右键组件 添加扩展功能
例如:给相关的组件添加额外的功能
[MenuItem("CONTEXT/组件名/按钮名")]
static void InitHealthAndSpeend(MenuCommand cmd)
{
}
(MenuCommand是当前操作的组件 cmd.context)
UnityEditor中选中项(Selection)
- Hierarchy面板选中的目标 可以使用 Selection.activeTransform(选中多个其值为选中的第一个)
- Hierarchy和Project选中目标:Selection.objects or Selection.gameObjects(返回值为一个数组)
Ctrl+Z的撤销功能
所有我们自己添加的扩展,如果没有记录的,删除了Ctrl+Z是不能恢复的
例如:
- 删除操作不可撤销
DestroyObjectImmeiate(o); - 删除操作可撤销
Undo.DestroyObjectImmeiate(o);
功能快捷键
-
单个字母:路径名后 空格 下划线
[MenuItem("Assets/MyTool1 _t",false,1000)]
该快捷键T -
组合键:
[MenuItem("Assets/MyTool1 %t",false,1000)]
该快捷键Ctrl+T
ctrl:%
shift:#
alt:&
关于功能方法判断
[MenuItem("Assets/MyTool1 %t",false,1000)]
其中间的参数作用,为true表示功能是否可用需要通过一个判断方法。
[MenuItem("Assets/MyTool1 %t",true,1000)]
static bool CheckFun()
{
return true;
}
[MenuItem("Assets/MyTool1 %t",true,1000)]
static void Fun()
{
//do something
}
注意:注解需一致,只是有一个返回值为bool的为判断方法
例如:选中有目标可用,否则置灰
[MenuItem("Assets/MyTool1 %t",true,1000)]
static bool CheckFun()
{
if(Selection.objects.length!=0)
return true;
return false;
}
[MenuItem("Assets/MyTool1 %t",true,1000)]
static void Fun()
{
//do something
}
直接在自定义脚本中,添加右键功能
ContextMenu和ContextMenuItem都在UnityEngine中,因此可以自己写在作用的脚本中,并且不用试静态的方法,前者修饰方法,后者修饰属性
//右键脚本:可以出现该方法
[ContextMenu("Do Something")]
void Do()
{
Debug.Log("DoSomething")
}
//右键属性:可以出现该方法
//第一个参数是按钮名 第二是方法名
[ContextMenuItem("Add Hp","AddHp")]
public int health;
private void AddHp()
{
health+=10;
}
创建对话框
创建的基础对话框:ScriptableWizard
using Editor
public Dialog:ScriptableWizard
{
[MenuItem("Tools/CreateDialog")]
static void CreateDialog()
{
ScriptableWizard.DisplayWizard<类名>("名字",“按钮名”);
}
public int addHealth=10;
public int addSpeed=1;
//按钮Create按钮时调用的函数
void OnWizardCreate()
{
Selection.gameObjects
//撤销 ,放在所有操作之前
Undo.RecordObject(hp,"sss");
}
//对话框中的数据变化后调用,创建时调用一次
void OnWizardUpdate()
{
}
//选中的对象发生改变
OnSelectionChanage()
{
}
}
wizard中的提示字符串
helpString= 显示在对话框顶部 ,errorString= 显示在对话框底部
第二按钮
ScriptableWizard.DisplayWizard<类名>("名字",“按钮名”,“第二个按钮名”)
第一个按钮点击会关闭窗口
第二个按钮不会关闭窗口
ShowNotification(new GUIContent("str"));
EditorPrefs保存编辑值(与PlayerPrefs同样适用方法)
SetInt
GetInt
显示进度条
EditorUtility.
DisplayProgressBar(........) 显示
ClearProgressBar() 关闭
创建自定义窗口
继承于EditorWindow
MyWindow window = EditorWindow.GetWindow
window.Show()
void OnGUI()
EditorGUILayout.Button()
Undo.RegisterCreatedObjectUndo(go,"create game")