Unity中,编辑器扩展允许开发者自定义编辑器界面和功能,可以大大提高工作效率,并且是不会打包在正式的包体中的。下面我将给大家讲解一些基础的API
我们的编辑器的脚本会放在一个Editor,这个文件下的脚本Unity会自动识别·,将不会打包。
编辑器扩展的代码都不需要继承MonoBehaviour
一.MenuItem
1.路径
我们想要在顶部栏添加功能,比如Unity自带的Assets、Window。我们需要使用Menultem关键字,首先需要引用UnityEditor的命名空间,("Test/Test1")是顶部栏出现路径
public class Test
{
[MenuItem("Test/Test1")]
static void Test1()
{
Debug.Log("Test1");
}
}
点击Tes1,就会执行Test1方法。
2.鼠标右击
大家都知道在Hierarchy窗口跟Assets窗口下鼠标右击都会有很多的方法,那如果我们也想这样应该怎么做呢?
如果有细心的伙伴,会发现Hierarchy窗口右击的方法与顶部菜单GameObject的方法是一样的。Assets的窗口右击的方法与顶部菜单Assets的方法是一样的。以Hierarchy窗口为例,那我们如果把Menultem的路径换成GameObject会不会就可以了呢?
public class Test
{
[MenuItem("GameObject/Test1")]
static void Test1()
{
Debug.Log("Test1");
}
}
答案是可以的,Assets也是一样的,大家可以自己TryTry。
2.方法验证
大家可以看到,Unity自带的编辑器扩展的方法,有一些按钮是灰色的,无法点击的,我们要实现这个功能就需要用到MenuItem的第二个参数,验证,我们需要提供一个MenuItem一样的方法,但是第二个参数是true的方法,并且返回是bool类型,当返回false时,按钮就不能被点击
public class Test
{
[MenuItem("Test/Test1",true)]
static bool Test1()
{
if(GameObject.FindObjectOfType<Camera>()!=null)return true;
else return false;
}
[MenuItem("Test/Test1", false)]
static void Test2()
{
Debug.Log("Test2");
}
}
3.方法分组
大家可以看到,Unity自带的方法都会分组,可以把同一类型的方法放在一起。我们自己的写的方法也可以分组,需要使用MenuItem第三个参数。priority相当于层级,两个层级相差小于11就被设置为一个组,数字越小,层级越大,方法越靠上
[MenuItem("Test/Test1", false,50)]
static void Test1()
{
Debug.Log("Test2");
}
[MenuItem("Test/Test3", false,10)]
static void Test3()
{
Debug.Log("Test2");
}
[MenuItem("Test/Test4", false, 9)]
static void Test4()
{
Debug.Log("Test2");
}
4.快捷键
# 表示 shift,& 表示 alt,% 表示 Ctrl
单独设置字母为快捷键需要在前面加上_
这个直接按下shift+T就会输出Test5
[MenuItem("Test/Test5 #t", false, 9)]
static void Test5()
{
Debug.Log("Test5");
}
二.Selection
Selection主要用于管理和获取当前选中的对象,它与鼠标操作密切相关
Selection.activeGameObject获取场景中的对象
Selection.activeObject获取对象(包括场景和文件夹内容,比如:预制件)
举个例子,删除鼠标场景中选中的物体
[MenuItem("Test/Test5 _t", false, 9)]
static void Test5()
{
foreach (var o in Selection.objects)
{
GameObject.DestroyImmediate(o);
}
}
三.进度条
EditorUtility.DisplayProgressBar是显示进度条,第一个参数是标题,第二个数详细信息,第三个是进度
EditorUtility.ClearProgressBar();关闭进度条
[MenuItem("Test/Test5 _t", false, 9)]
static void Test5()
{
EditorUtility.DisplayProgressBar("进度条", "1111", 0);
int count = 0;
foreach (var o in Selection.objects)
{
GameObject.DestroyImmediate(o);
EditorUtility.DisplayProgressBar("进度条", "1111", (float)count/ Selection.objects.Length*100);
count++;
}
EditorUtility.ClearProgressBar();
}
四.窗口
1.ScriptableWizard
我们要创建出窗口,脚本需要继承ScriptableWizard,ScriptableWizard给我们封装了很多的方法,我们直接调用就可以了,DisplayWizard是打开一个窗口
1.创造窗口
using UnityEditor;
public class MovePos : ScriptableWizard
{
[MenuItem("Test/Move")]
static void Move()
{
ScriptableWizard.DisplayWizard<MovePos>("移动物体");
}
}
2.按钮
我们可以修改面板按钮Create的名字,并且可以创造其他的按钮
[MenuItem("Test/Move")]
static void Move()
{
ScriptableWizard.DisplayWizard<MovePos>("移动物体","创造","按钮2");
}
3.监听按钮
我们也可以监听创建面板上的Create按钮,方法也是内置的
private void OnWizardCreate()
{
Debug.Log("点击了Create按钮");
}
private void OnWizardOtherButton()
{
Debug.Log("点击了按钮2");
}
4.提示消息
private void OnWizardUpdate()
{
if (Selection.activeGameObject == null)
errorString = "鼠标未选中物体";
else
helpString="鼠标选中的物体是"+ Selection.activeGameObject.name;
}
2.EditorWindow
EditorWindow设置的窗口是长期存在的窗口,类似Unity自带的窗口。
1.创建窗口
首先脚本需要继承EditorWindow类
public class Window : EditorWindow
{
[MenuItem("Test/CreatWindow")]
static void CreatWindow()
{
EditorWindow.GetWindow<Window>("我的窗口");
}
}
2.OnGUI
我们在window创建,需要用到OnGUI的API
创建文本框跟按钮
private void OnGUI()
{
GUILayout.TextField("窗口");
GUILayout.Button("创建");
}
3.示例
下面我们通过输入的名称,判断按钮点击,创建一个物体
string name = "";
private void OnGUI()
{
name= GUILayout.TextField(name);
if (GUILayout.Button("创建"))
{
GameObject g=new GameObject(name);
}
}