Unity实用功能之扩展编辑器-窗口绘制(二)

1,042 阅读5分钟

这是我参与8月更文挑战的第23天,活动详情查看:8月更文挑战

概述

上一篇文章我们说到,在unity中通过编辑器扩展,美化了Inspector面板,其实unity的编辑器扩展还有非常多的功能,除了能够为Unity编辑器进行控件绘制,还可以为编辑器自行创建一个新的窗口,并且设置他的窗口布局。接下来我们就来共同学习下,在Unity编辑器中如何创建一个自定义布局的窗口。

功能实现

想要创建一个窗口,那么脚本就必须要继承EditorWindow,脚本继承EditorWindow的同时,脚本必须要引用using UnityEditor;命名空间,否则继承就是错误的。
首先我们创建一个继承EditorWindow脚本,同样要放到Editor文件夹下

using UnityEditor;

public class EditorWindowTest : EditorWindow
{ 
}

我们创建一个静态方法用来打开窗口,同时在这个方法里,我们可以对窗口进行自定义的设计。

static void OpenWindow()
{
}

想要将这个方法显示到Unity编辑器中,只继承Editorwindow还不行,我们还需要使用到unity的另一个特性[MenuItem]

我们先一起来看一下MenuItem
MenuItem是UnityEditor下的属性,它是对编辑器的扩展,主要有两大作用:

  1. 在主菜单中添加菜单项,也就是在以下编辑器部分添加,这是一个很重要的用途,在开发插件的时候经常用到。
  2. 在属性面板的组件的上下文中添加菜单项,针对编辑器中已有组件的扩展 注意:函数一般都是私有的,而且必须是静态函数才能使用MenuItem属性。为什么必须是static函数呢,因为该类可以不用实例化,不用继承自MonoBehavior,比如给刚体添加一个重置属性功能,就不需要添加脚本组件,因此,我们就可以在一个扩展脚本中集中很多类似的菜单项。所以上面的代码我们用到的是static。 一般常用的是
    public MenuItem(string itemName);

itemName是菜单路径名称,可添加菜单快捷键:(空格后加如下符号设置),如下:

_w 单一的快捷键 W 
#w shift+w 
%w ctrl+w 
&w Alt+w

MenuItem我们就暂时先介绍到这里,接下来回归正题,给我们的方法设置一个路径,如:在菜单栏Tools下的OpenWindow

[MenuItem("Tools/OpenWindow")]
static void OpenWindow()
{
}

这样菜单栏就出现我们刚刚写的方法了 image.png 接下来我们创建一个窗口,首先规定一下窗口的大小

Rect rect = new Rect(0, 0, 500, 500);

设置完大小,就只剩下创建窗体了

EditorWindowTest window = (EditorWindowTest)EditorWindow.GetWindowWithRect(typeof(EditorWindowTest), rect, true, "自定义创建窗口");
window.Show();

写完之后,点击菜单栏就会出现如下效果

展示7.gif 到这里窗口我们就创建成功了,当然这仅仅是一个进本的窗口,什么内容都没有,下面我们就一起来丰富一下这个窗口,给窗口加输入框、添加一个文本框显示鼠标位置、添加一个选择贴图功能,打开关闭通知栏,关闭窗口等功能。这些功能都是写在OnGUI方法中的

添加输入框控件

 text = EditorGUILayout.TextField("请输入内容:", text);

image.png 打开通知

首先创建一个打开通知的按钮

GUILayout.Button("打开通知", GUILayout.Width(200))

然后在写打开通知栏的方法

 this.ShowNotification(new GUIContent("这是一条通知消息"));

效果如下 展示8.gif 关闭通知

关闭通知和上述方法基本差不多,先创建按钮在写方法

if (GUILayout.Button("关闭通知", GUILayout.Width(200)))
{
    //关闭通知栏
    this.RemoveNotification();
}

添加文本框显示鼠标位置

获取鼠标位置的方法(有缺点,不是所有地方都能取到)

Event.current.mousePosition

添加文本框并显示鼠标位置

EditorGUILayout.LabelField("鼠标位置:", Event.current.mousePosition.ToString());

展示9.gif 选择贴图

选择贴图功能和上一篇写的基本都一样

texture = EditorGUILayout.ObjectField("选择贴图", texture, typeof(Texture), true) as Texture;

以上功能整体效果就是如下效果 image.png

知识点拓展

下面写点扩展编辑器可能会用到的生命周期
当窗口获得焦点时

private void OnFocus()
{
    Debug.Log("当窗口获得焦点时调用一次");
}

当窗口失去焦点时

private void OnLostFocus()
{
    Debug.Log("当窗口失去焦点时调用一次");
}

当Hierarchy视图中的任何对象发生改变时

private void OnHierarchyChange()
{
    Debug.Log("当Hierarchy视图中的任何对象发生改变时调用一次");
}

当Project视图中的任何对象发生改变时

private void OnProjectChange()
{
    Debug.Log("当Project视图中的任何对象发生改变时调用一次");
}

窗口面板的热更新

private void OnInspectorUpdate()
{
    Debug.Log("窗口面板的热更新");
    //开启窗口重绘,否则信息不会刷新
    this.Repaint();
}

当窗口处于开启状态,并且在Hierarchy视图中选择某游戏对象时

private void OnSelectionChange()
{
    //当窗口处于开启状态,并且在Hierarchy视图中选择某游戏对象时调用
    foreach (var item in Selection.transforms)
    {
        //有可能多选,这里开启一个循环
        Debug.Log("OnSelectionChange:" + item.name);
    }
}

当窗口关闭时

private void OnDestroy()
{
    Debug.Log("当窗口关闭时调用");
}

一起来看一下最终效果

展示10.gif

源码地址

GitHub下载地址:点击这里跳转下载

写在最后

本篇文章主要是介绍了一下,Unity编辑器如何进行窗口扩展,以便在开发过程中能够更加的方便,下一篇文章将继续介绍在Unity中如何对编辑器进行扩展,功能也非常实用,欢迎大家共同学习交流。