在Unity中我们常常扩展各种编辑窗口,创建自己的自定义编辑器窗口,这些窗口可以自由浮动,也可以作为选项卡停靠,就像 Unity 界面中的原生窗口一样。
在Unity中创建自定义窗口通常是通过UnityEditor的EditorWindow类来实现的。以下是创建一个简单自定义窗口的步骤和示例代码:
添加功能步骤:
1、创建一个继承自EditorWindow的新C#脚本。
2、添加一个静态方法来打开窗口。
3、在此方法中,使用GetWindow<自定义窗口类>()打开窗口,并重写窗口的OnGUI方法来定义窗口界面。
示例代码:
using UnityEngine;
using UnityEditor;
public class CustomWindow : EditorWindow
{
// 添加窗口菜单项
[MenuItem("MyWindow/Open Custom Window")]
public static void OpenWindow()
{
// 打开窗口
GetWindow<CustomWindow>("My Custom Window");
}
private void OnGUI()
{
// 在这里定义窗口界面
GUILayout.Label("Hello, this is my custom window!");
if (GUILayout.Button("Click Me"))
{
// 处理按钮点击事件
Debug.Log("Button Clicked!");
}
}
}
将上述代码保存到项目中的Editor文件夹下的C#脚本文件中(如果没有此文件夹,请创建一个)。然后,您可以通过Unity编辑器顶部菜单的"MyWindow"路径来打开您的自定义窗口。每次运行Unity编辑器时,都会检查Editor文件夹中的脚本,并根据MenuItem属性添加相应的菜单项。
目标:
1、了解一些属性的使用
2、创建一个自定义窗口
最终目标:
利用学到的东西制作自己的工具(自定义的窗口、Inspector、菜单、插件等等)。
一、EditorWindow编辑器窗口类
1、在 Unity 中,EditorWindow 和 ScriptableWizard 都是用于创建自定义编辑器界面的类。
2、EditorWindow 是用于创建自定义编辑器窗口的类,可以包含自定义的 GUI 元素和逻辑。它通常用于创建工具窗口、面板或者其他自定义的编辑器界面。
3、ScriptableWizard 是用于创建向导式界面的类,可以帮助用户完成特定的任务。通常用于引导用户完成一系列步骤,例如创建新的资产、配置项目设置等。与 EditorWindow 相比,向导更加注重交互性和引导性,常用于流程化的操作步骤。
二、EditorWindow参数总览
常用参数 | 描述 |
---|
position | 窗口在屏幕空间中的理想位置。 |
titleContent | 用于绘制 EditorWindow 标题的 GUIContent。 |
Close | 关闭编辑器窗口。 |
Show | 显示 EditorWindow 窗口。 |
ShowAsDropDown | 显示包含下拉菜单和样式的窗口。 |
ShowAuxWindow | 在辅助窗口中显示编辑器窗口。 |
ShowModal | 显示模态编辑器窗口。 |
ShowNotification | 显示通知消息。 |
ShowPopup | 使用弹出式框架显示编辑器窗口。 |
ShowUtility | 将 EditorWindow 显示为浮动实用程序窗口。 |
CreateWindow | 创建类型为 T 的 EditorWindow。 |
FocusWindowIfItsOpen | 聚焦发现的第一个指定类型的 EditorWindow(如果已打开)。 |
GetWindow | 返回当前屏幕上的第一个 windowType 类型的 EditorWindow。 |
GetWindowWithRect | 返回当前屏幕上第一个 t 类型的 EditorWindow。 |
HasOpenInstances | 检查编辑器窗口是否已打开。 |
OnBecameInvisible | 在窗口从容器视图中删除或在 EditorWindow 的选项卡式集合中不再可见后调用。 |
OnBecameVisible | 将窗口添加到容器视图后调用。 |
OnDestroy | 调用 OnDestroy 以关闭 EditorWindow 窗口。 |
OnFocus | 在窗口获得键盘焦点时调用。 |
OnGUI | 在此处实现您自己的 Editor GUI。 |
OnHierarchyChange | 处理程序,用于在层级视图中的对象或对象组发生更改时发送的消息。 |
OnInspectorUpdate | OnInspectorUpdate 以每秒 10 帧的速度调用,以便检视面板有机会进行更新。 |
OnLostFocus | 在窗口失去键盘焦点时调用。 |
OnProjectChange | 处理程序,用于在项目状态发生更改时发送的消息。 |
OnSelectionChange | 每当选择发生更改时调用。 |
三、EditorWindow 的生命周期
1、打开
OnEnable():当打开界面的时候调用
OnFocus():当该窗口被聚焦(点击该窗口)
2、打开中
OnGUI():当渲染 UI 的时候调用
OnSelectionChange():当选择发生更改时调用,选中的可选项(在 Project 和 Hierarchy 视图中)
OnInspectorUpdate():当属性界面更新时,几乎一直在更
OnHierarchyChange():当场景层次界面发生改变时调用 ");// 在 Hierarchy 界面改变(增加、减少物体)
OnProjectChange():当项目发生更改时调用 ");// 在 Project 视图删除、增加文件
OnValidate():当拖拽式赋值时调用
3、关闭
OnLostFocus():从该窗口离开时调用(点击非窗口外其他地方)
OnDisable():当隐藏的时候调用
OnDestroy():当销毁的时候调用
四、CreateWindow、GetWindow、GetWindowWithRect
1、在 Unity 编辑器中,CreateWindow()、GetWindow() 和 GetWindowWithRect() 是用于处理窗口的函数,但它们的功能和使用场景有所不同。
1、CreateWindow():这个函数通常用于创建一个新的窗口。在 Unity 编辑器中,这可能涉及到创建一个新的 Inspector 窗口、Console 窗口或其他自定义窗口。CreateWindow () 需要指定窗口类型(例如 WindowType.Inspector 或 WindowType.Console)以及其他可能的参数,如窗口标题和大小。
3、GetWindow()::这个函数用于获取一个已经存在的窗口。它通常用于需要引用已打开的窗口的情况,例如,你可能想关闭一个已经打开的 Inspector 窗口。
4、GetWindowWithRect()::这个函数比较特殊,它不仅仅是为了获取一个窗口,而且还要通过一个指定的矩形区域获取。这对于需要在给定屏幕区域中查找和操作窗口非常有用。比如你可能想在指定的屏幕区域查找 Console 窗口。
5、在使用这些函数时,通常需要注意以下几点:
CreateWindow() 用于创建新窗口,而 GetWindow() 和 GetWindowWithRect() 用于获取已存在的窗口。
GetWindow() 和 GetWindowWithRect() 通常用于操作已打开的窗口,例如关闭它们或获取它们的引用。
GetWindowWithRect() 特别适用于在特定屏幕区域查找窗口,这在处理多显示器或多窗口环境时非常有用。
代码示例
using UnityEditor;
using UnityEngine;
public class WindowExample : EditorWindow
{
private static WindowExample window;//窗体实例
//显示窗体
[MenuItem("MyWindow/Second Window")]
private static void ShowWindow()
{
window = EditorWindow.GetWindow<WindowExample>("Window Example");
window.Show();
}
//显示时调用
private void OnEnable()
{
Debug.Log("OnEnable");
}
//绘制窗体内容
private void OnGUI()
{
EditorGUILayout.LabelField("Your Second Window", EditorStyles.boldLabel);
}
//固定帧数调用
private void Update()
{
Debug.Log("Update");
}
//隐藏时调用
private void OnDisable()
{
Debug.Log("OnDisable");
}
//销毁时调用
private void OnDestroy()
{
Debug.Log("OnDestroy");
}
}
五、ScriptableWizard参数总览
Unity为开发者提供了一个简单的快速创建对话框窗体的方式,只需要继承自ScriptableWizard类,我们容易发现ScriptableWizard实际上是继承自EditorWindow,只是做了一层封装,该类窗体一般用于快捷功能的操作,例如统一修改场景中多个对象的位置等信息。
常用参数 | 描述 |
---|
createButtonName | 允许您设置向导的 Create 按钮上显示的文本。 |
errorString | 允许您设置向导的错误文本。 |
helpString | 允许您设置向导的帮助文本。 |
isValid | 允许您启用向导 Create 按钮,或者将其禁用,从而使用户无法点击。 |
otherButtonName | 允许您设置向导的可选 Other 按钮上显示的文本。忽略此参数将不显示该按钮。 |
OnWizardCreate | 当用户单击 Create 按钮时,将调用此函数。 |
OnWizardOtherButton | 允许您在用户单击 Others 按钮时提供操作。 |
OnWizardUpdate | 在向导打开或者用户在向导中更改内容时,将调用此函数。 |
六、区别OnWizardCreate、OnWizardOtherButton、OnWizardUpdate
OnWizardCreate:
当向导被创建时调用。
通常用于初始化向导的状态或设置。
OnWizardOtherButton:
当用户在向导界面上点击非标准按钮(如 “下一步”、“上一步” 或自定义按钮)时调用。
你可以根据需要重写此方法以处理非标准按钮的点击事件。
OnWizardUpdate:
在向导的当前步骤被更新时调用。
通常用于根据用户输入或其他条件更新向导的当前步骤内容。
代码样例
using UnityEditor;
using UnityEngine;
public class WindowExample : ScriptableWizard
{
public float range = 500;
public Color color = Color.red;
[MenuItem("GameObject/Create Light Wizard")]
static void CreateWizard()
{
ScriptableWizard.DisplayWizard<WindowExample>("Create Light", "Create", "Apply");
如果您不想使用辅助按钮,只需将其省略即可:
//ScriptableWizard.DisplayWizard<WizardCreateLight>("Create Light", "Create");
}
//显示在向导窗口里的变量
public float speedValue = 10;
public bool canShoot = true;
//用户单击创建按钮进行调用,固定用法,点击后向导窗口关闭
private void OnWizardCreate()
{
Debug.Log("Create : Change By Value");
//一般在这里做最终的处理
//比如在这里可以获取选中的全部object,再利用向导窗口里填写的变量批量改变文件数值
}
//用户单击自定义其他按钮时进行调用,固定用法,点击后向导窗口不会关闭
private void OnWizardOtherButton()//在这里是一个初始化数据的功能
{
Debug.Log("Clear");
speedValue = 0;
canShoot = false;
ShowNotification(new GUIContent("数据已经初始化完毕"));
//该功能用来弹出一个小提示通知信息,几秒后自动消失
}
//打开向导或者更改向导里的内容时进行调用,固定用法
private void OnWizardUpdate()
{
Debug.Log("Change");
//当在向导窗口里一些操作错误或者不规范时,可以通过设置helpString和errorString来进行提示操作人员
helpString = "文中某某变量填写规范为"XXXX+DDDD+SS"";
errorString = "文中某某变量填写不规范";
//编辑器模式下,可以使用EditorPrefs进行数据的存取,用法与游戏运行时PlayerPrefs用法一致
EditorPrefs.SetFloat("key", speedValue);
}
//当在工程里选中操作有变化时进行调用
private void OnSelectionChange()
{
OnWizardUpdate();
}
}
七、PopupWindow弹出窗口
用于显示从 PopupWindowContent 继承的弹出窗口的类。
弹出窗口没有边距,不可拖动,也无法调节大小。此外,它们还会在失去焦点时自动关闭。它们用于显示短暂的信息或选项。
编辑器中的弹出窗口的一个示例是编辑器“Scene View”工具栏中的“Scene View Effects”选项:
下面是一个自定义弹出窗口的示例,此弹出窗口通过编辑器窗口中的一个按钮显示。该弹出窗口具有三个开关值,并会在失去焦点时自动关闭。此示例以两个脚本的形式提供。第一个脚本定义可通过菜单项打开的编辑器窗口。该编辑器窗口具有一个可显示弹出窗口的按钮。第二个脚本以一个单独的类的形式定义弹出窗口本身的内容。
首先,下面是启动弹出窗口的简单编辑器窗口的代码:
using UnityEngine;
using UnityEditor;
public class EditorWindowWithPopup : EditorWindow
{
// Add menu item
[MenuItem("Example/Popup Example")]
static void Init()
{
EditorWindow window = EditorWindow.CreateInstance<EditorWindowWithPopup>();
window.Show();
}
Rect buttonRect;
void OnGUI()
{
{
GUILayout.Label("Editor window with Popup example", EditorStyles.boldLabel);
if (GUILayout.Button("Popup Options", GUILayout.Width(200)))
{
PopupWindow.Show(buttonRect, new PopupExample());
}
if (Event.current.type == EventType.Repaint)
buttonRect = GUILayoutUtility.GetLastRect();
}
}
}
接下来,下面是弹出窗口本身的代码:
using UnityEngine;
using UnityEditor;
public class PopupExample : PopupWindowContent
{
bool toggle1 = true;
bool toggle2 = true;
bool toggle3 = true;
public override Vector2 GetWindowSize()
{
return new Vector2(200, 150);
}
public override void OnGUI(Rect rect)
{
GUILayout.Label("Popup Options Example", EditorStyles.boldLabel);
toggle1 = EditorGUILayout.Toggle("Toggle 1", toggle1);
toggle2 = EditorGUILayout.Toggle("Toggle 2", toggle2);
toggle3 = EditorGUILayout.Toggle("Toggle 3", toggle3);
}
public override void OnOpen()
{
Debug.Log("Popup opened: " + this);
}
public override void OnClose()
{
Debug.Log("Popup closed: " + this);
}
}
以上每段代码应另存为以其类名称命名的单独文件。这些代码都不是行为,因此无需将它们放在游戏对象上。将它们放在项目中后,通过转到新的“Example”菜单并选择“Popup Example”即可试用。然后,单击新编辑器窗口中的按钮可显示弹出选项窗口
八、PopupWindow参数总览
受保护的函数
OnDisable | 请参阅 ScriptableObject.OnEnable。 |
OnEnable | 请参阅 ScriptableObject.OnDisable。 |
静态函数
Show | 显示具有给定 PopupWindowContent 的弹出窗口。 |
继承的成员
静态变量
focusedWindow | 当前已获得键盘焦点的 EditorWindow。(只读) |
mouseOverWindow | 当前在鼠标光标下的 EditorWindow。(只读) |
变量
autoRepaintOnSceneChange | 窗口是否会在场景每次发生变化时自动重绘? |
maximized | 此窗口是否已最大化? |
maxSize | 此窗口的最大大小。 |
minSize | 此窗口的最小大小。 |
position | 窗口在屏幕空间中的理想位置。 |
titleContent | 用于绘制 EditorWindow 标题的 GUIContent。 |
wantsMouseEnterLeaveWindow | 检查是否已在此编辑器窗口的 GUI 中收到 MouseEnterWindow 和 MouseLeaveWindow 事件。 |
wantsMouseMove | 检查是否已在此编辑器窗口的 GUI 中收到 MouseMove 事件。 |
hideFlags | 该对象应该隐藏、随场景一起保存还是由用户修改? |
name | 对象的名称。 |
公共函数
BeginWindows | 标记所有弹出窗口的开始区域。 |
Close | 关闭编辑器窗口。 |
EndWindows | 关闭由 EditorWindow.BeginWindows 开始的窗口组。 |
Focus | 将键盘焦点移动到另一个 EditorWindow。 |
RemoveNotification | 停止显示通知消息。 |
Repaint | 重绘窗口。 |
SendEvent | 将事件发送到窗口。 |
Show | 显示 EditorWindow 窗口。 |
ShowAsDropDown | 显示包含下拉菜单和样式的窗口。 |
ShowAuxWindow | 在辅助窗口中显示编辑器窗口。 |
ShowNotification | 显示通知消息。 |
ShowPopup | 使用弹出式框架显示编辑器窗口。 |
ShowUtility | 将 EditorWindow 显示为浮动实用程序窗口。 |
GetInstanceID | 返回对象的实例 ID。 |
ToString | 返回对象的名称。 |
静态函数
FocusWindowIfItsOpen | 聚焦发现的第一个指定类型的 EditorWindow(如果已打开)。 |
GetWindow | 返回当前屏幕上第一个 t 类型的 EditorWindow。 |
GetWindowWithRect | 返回当前屏幕上第一个 t 类型的 EditorWindow。 |
Destroy | 移除 GameObject、组件或资源。 |
DestroyImmediate | 立即销毁对象 /obj/。强烈建议您改用 Destroy。 |
DontDestroyOnLoad | 在加载新的 Scene 时,请勿销毁 Object。 |
FindObjectOfType | 返回第一个类型为 type 的已加载的激活对象。 |
FindObjectsOfType | 返回所有类型为 type 的已加载的激活对象的列表。 |
Instantiate | 克隆 original 对象并返回克隆对象。 |
CreateInstance | 创建脚本化对象的实例。 |
运算符
bool | 该对象是否存在? |
operator != | 比较两个对象是否引用不同的对象。 |
operator == | 比较两个对象引用,判断它们是否引用同一个对象。 |
消息
Awake | 在新窗口打开时调用。 |
OnDestroy | 调用 OnDestroy 以关闭 EditorWindow 窗口。 |
OnFocus | 在窗口获得键盘焦点时调用。 |
OnGUI | 在此处实现您自己的 Editor GUI。 |
OnHierarchyChange | 处理程序,用于在层级视图中的对象或对象组发生更改时发送的消息。 |
OnInspectorUpdate | OnInspectorUpdate 以每秒 10 帧的速度调用,以便检视面板有机会进行更新。 |
OnLostFocus | 在窗口失去键盘焦点时调用。 |
OnProjectChange | 处理程序,用于在项目状态发生更改时发送的消息。 |
OnSelectionChange | 每当选择发生更改时调用。 |
Update | 在所有可见窗口上每秒调用多次。 |
Awake | 当 ScriptableObject 脚本启动时调用此函数。 |
OnDestroy | 当脚本化对象将销毁时调用此函数。 |