UEDL2——自定义窗口拓展

本章代码关键字

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
EditorWindow                            //编辑器窗口基类,所有的编辑器窗口类都必须继承它
//继承EditorWindow的窗口类,会自带一些事件回调函数,当触发对应事件时会自动进入
OnHierarchyChange() { } //当场景中的层次结构(Hierarchy)发生变化时调用
OnFocus() { } //当窗口获得焦点时调用
OnLostFocus() { } //当窗口失去焦点时调用
OnProjectChange() { } //当项目资源发生变化时调用
OnInspectorUpdate() { } //在检视器(Inspector)面板更新时调用
OnSelectionChange() { } //当选择的对象发生变化时调用
//静态成员
EditorWindow.focusedWindow //当前已获得键盘焦点的 EditorWindow
EditorWindow.mouseOverWindow //当前在鼠标光标下的 EditorWindow
EditorWindow.CreateWindow<>() //创建窗口,如果允许一个窗口有多个可以用该API创建窗口
EditorWindow.GetWindow<>() //通过它我们可以创建一个窗口对象,只使用该方法可以保证窗口唯一性
EditorWindow.GetWindowWithRect<>() //返回一个指定位置、大小的窗口,只使用该方法同样可以保证窗口唯一性
EditorWindow.HasOpenInstances<>() //检查编辑器窗口是否打开
//窗口成员
editorWindow.titleContent //窗口标题名,该属性需要一个GUIContent对象,实例化对象时传入要显示的标题名即可
editorWindow.position //窗口位置大小信息,设置该属性可以改变窗口的显示位置与大小
editorWindow.wantsMouseEnterLeaveWindow //如果设置为 true,则每当鼠标进入或离开窗口时,该窗口都会收到一次 OnGUI() 调用
editorWindow.Show() //显示面板,在创建或者获取到窗口对象后,执行Show()方法即可显示窗口
editorWindow.Repaint() //重绘窗口
editorWindow.Close() //关闭编辑器窗口

编辑器窗口类

命名空间:UnityEditor
类名:EditorWindow

当我们想要为Unity拓展一个自定义窗口时,我们只需要实现一个继承了EditorWindow​的类即可
并且在该类的OnGUI()​函数中编写面板控件相关的逻辑:如何绘制详见:IMGUI

对于编辑器窗口可以额外绘制的控件,请看:EditorGUI

1
2
3
4
5
6
7
8
9
10
11
12
13
14
using UnityEditor;
using UnityEngine;

public class Lesson2 : EditorWindow
{
private void OnGUI()
{
GUILayout.Label("测试文本");
if (GUILayout.Button("测试按钮"))
{
Debug.Log("Test");
}
}
}

显示编辑器窗口

用上节课学习的添加自定义页签的知识,添加一个自定义页签用于开启窗口调用EditorWindow.GetWindow()

该方法有很多种重载,其中的主要参数一般有:

  • <Type>​或<T>​:窗口类的类型,使用泛型参数或者Type​类型参数
  • utility​:为 true​ 可创建浮动实用程序窗口,设置为 false​ 可创建正常窗口。所谓浮动窗口就是可以自由拖动自由改变大小
  • title​:窗口标题
  • focus​:是否为窗口提供焦点,即一开始就选中它(如果已存在),(如果GetWindow​创建新窗口,则将始终获得焦点)
  • desiredDockNextTo​:窗口试图停靠到其上的 EditorWindow​ 类型的数组

一般参数只使用第一个参数的重载就够用了

创建窗口对象,之后调用对象的Show()​方法即可显示窗口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
using UnityEditor;
using UnityEngine;

public class Lesson2 : EditorWindow
{
[MenuItem("Unity编辑器拓展/Lesson2/显示自定义面板")]
private static void ShowWindow()
{
//获取窗口对象,若窗口未创建就先创建,该方法保证窗口的唯一性
Lesson2 window = EditorWindow.GetWindow<Lesson2>();
//显示窗口
window.Show();
}

private void OnGUI()
{
GUILayout.Label("测试文本");
if (GUILayout.Button("测试按钮"))
{
Debug.Log("Test");
}
}
}

以上代码就会在菜单栏里添加Unity编辑器拓展/Lesson2/显示自定义面板选项​,点击后就会显示窗口
再点击显示出的窗口的测试按钮,就会显示输出Test

image

窗口事件回调函数

继承EditorWindow​的窗口类,会自带一些事件回调函数,当触发对应事件时会自动进入

  • OnHierarchyChange()​:当场景中的层次结构(Hierarchy)发生变化时调用。
    例如,当游戏对象被创建、删除或重命名时触发。

    1
    2
    3
    4
    private void OnHierarchyChange()
    {
    Debug.Log("Hierarchy窗口内容发生改变");
    }
  • OnFocus()​:当窗口获得焦点时调用。
    在这个方法中,你可以执行一些在窗口获得焦点时需要进行的操作。

    1
    2
    3
    4
    private void OnFocus()
    {
    Debug.Log("窗口获得焦点(被点击选中)");
    }
  • OnLostFocus()​:当窗口失去焦点时调用。
    通常在这个方法中执行一些在窗口失去焦点时需要进行的清理工作。

    1
    2
    3
    4
    private void OnLostFocus()
    {
    Debug.Log("窗口失去焦点(不再选中)");
    }
  • OnProjectChange()​:当项目资源发生变化时调用。
    例如,当添加、删除或修改项目中的文件时触发。

    1
    2
    3
    4
    private void OnProjectChange()
    {
    Debug.Log("Project窗口内容发生改变");
    }
  • OnInspectorUpdate()​:在检视器(Inspector)面板更新时调用。
    可以在这个方法中执行需要在检视器面板刷新时进行的逻辑,比如更新显示的信息

    1
    2
    3
    4
    private void OnInspectorUpdate()
    {
    Debug.Log("Inspector窗口内容发生改变");
    }
  • OnSelectionChange()​:当选择的对象发生变化时调用。
    在这个方法中,你可以执行与所选对象相关的操作,以确保编辑器窗口的内容与当前选择保持同步。

    1
    2
    3
    4
    private void OnSelectionChange()
    {
    Debug.Log("选中对象改变");
    }

窗口中常用的生命周期函数

除了OnGUI()​这个方法是必不可少的以外,这里的所有生命周期函数效果都与MonoBehaviour​的生命周期函数一致

  • OnEnable()​:当窗口被激活时调用,通常在窗口创建时会调用一次。
    在这个方法中,你可以进行一些初始化工作,例如注册事件监听器或设置初始变量。
  • OnGUI()​:每帧都会调用此方法,用于绘制编辑器窗口的 GUI。
    在这个方法中,你可以使用 GUILayout 或 EditorGUILayout 等类创建界面元素,以便用户与窗口进行交互。
  • OnDestroy()​:当窗口被销毁时调用,通常在关闭编辑器或切换场景时触发。
    在这里进行最终的清理工作,确保没有未释放的资源。
  • Update()​:在编辑器窗口每帧更新时调用。
    通常在这里执行一些需要在每帧进行的逻辑

编辑器窗口类中的常用成员

Unity官方文档有关于编辑器窗口类的API说明:https://docs.unity.cn/cn/2022.3/ScriptReference/EditorWindow.html

  • 静态变量

    1. focusedWindow​:当前已获得键盘焦点的 EditorWindow​。(只读)
    2. mouseOverWindow​:当前在鼠标光标下的 EditorWindow​。(只读)
  • 静态函数

    • CreateWindow()​:创建窗口,如果允许一个窗口有多个可以用该API创建窗口

      1
      2
      3
      4
      5
      6
      [MenuItem("Unity编辑器拓展/Lesson2/显示自定义面板")]
      private static void ShowWindow()
      {
      Lesson2 window = EditorWindow.CreateWindow<Lesson2>();
      window.Show();
      }

      image

    • GetWindow()​:通过它我们可以创建一个窗口对象,只使用该方法可以保证窗口唯一性

      这是我们最常用的获取和创建窗口对象的方法,该方法有多个重载,详细请看:显示编辑器窗口

      1
      2
      3
      4
      5
      6
      7
      8
      [MenuItem("Unity编辑器拓展/Lesson2/显示自定义面板")]
      private static void ShowWindow()
      {
      //获取窗口对象,若窗口未创建就先创建,该方法保证窗口的唯一性
      Lesson2 window = EditorWindow.GetWindow<Lesson2>();
      //显示窗口
      window.Show();
      }
    • GetWindowWithRect()​:返回一个指定位置、大小的窗口,只使用该方法同样可以保证窗口唯一性

      相对于GetWindow()​,它多了一个Rect​类型参数要传入,来确认窗口位置与大小
      在这里设置了窗口的大小后,窗口的大小将不能被改变,除非依附于某个窗口,
      而窗口的实际显示位置是由上次关闭时位置决定的,除非第一次打开窗口

      1
      2
      3
      4
      5
      6
      [MenuItem("Unity编辑器拓展/Lesson2/显示自定义面板")]
      private static void ShowWindow()
      {
      Lesson2 window = EditorWindow.GetWindowWithRect<Lesson2>(new Rect(10, 10, 200, 200));
      window.Show();
      }
    • HasOpenInstances()​:检查编辑器窗口是否打开

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      [MenuItem("Unity编辑器拓展/Lesson2/显示自定义面板")]
      private static void ShowWindow()
      {
      Lesson2 window = EditorWindow.GetWindowWithRect<Lesson2>(new Rect(10, 10, 200, 200));
      window.Show();
      if (EditorWindow.HasOpenInstances<Lesson2>())
      {
      Debug.Log("窗口已经打开!");
      }
      }
  • 成员变量

    • titleContent​:窗口标题名

      该属性需要一个GUIContent​对象,实例化对象时传入要显示的标题名即可

      1
      2
      3
      4
      5
      6
      7
      [MenuItem("Unity编辑器拓展/Lesson2/显示自定义面板")]
      private static void ShowWindow()
      {
      Lesson2 window = EditorWindow.GetWindow<Lesson2>();
      window.titleContent = new GUIContent("我的窗口");
      window.Show();
      }

      image

    • positon​:窗口位置大小信息

      设置该属性可以改变窗口的显示位置与大小

      1
      2
      3
      4
      5
      6
      7
      [MenuItem("Unity编辑器拓展/Lesson2/显示自定义面板")]
      private static void ShowWindow()
      {
      Lesson2 window = EditorWindow.GetWindow<Lesson2>();
      window.position = new Rect(10, 10, 300, 200);
      window.Show();
      }
    • wantsMouseEnterLeaveWindow​:如果设置为 true​,则每当鼠标进入或离开窗口时,该窗口都会收到一次 OnGUI()​ 调用

      1
      2
      3
      4
      5
      6
      7
      [MenuItem("Unity编辑器拓展/Lesson2/显示自定义面板")]
      private static void ShowWindow()
      {
      Lesson2 window = EditorWindow.GetWindow<Lesson2>();
      window.wantsMouseEnterLeaveWindow = true;
      window.Show();
      }
  • 成员函数

    • Show()​:显示面板

      在创建或者获取到窗口对象后,执行Show()​方法即可显示窗口

      显示窗口的详细步骤请看:显示编辑器窗口

      1
      2
      3
      4
      5
      6
      7
      8
      [MenuItem("Unity编辑器拓展/Lesson2/显示自定义面板")]
      private static void ShowWindow()
      {
      //获取窗口对象,若窗口未创建就先创建,该方法保证窗口的唯一性
      Lesson2 window = EditorWindow.GetWindow<Lesson2>();
      //显示窗口
      window.Show();
      }
    • Repaint()​:重绘窗口

      1
      editorWindow.Repaint();
    • Close()​:关闭编辑器窗口

      1
      editorWindow.Close();