在Unity中创建编辑器Windows

在过去十年中,Unity一直是开发游戏的绝佳平台,为开发人员提供大量工具:渲染引擎​​,物理引擎,动画系统,音频混合器等。但是,在创建关卡或生成游戏内数据时,Unity不足,因为每个游戏都是独一无二的,需要不同种类的工具。值得庆幸的是,Unity为我们的开发人员提供了一个API,可以创建我们自己的编辑器窗口,自定义抽屉和检查器面板。在这一系列的博客文章中,我将向您展示我们如何在Gram Games中为设计师和艺术家在Unity中开发自定义编辑器。我们将首先创建一个编辑器窗口,在其中放置两个面板,然后使其可调整大小。在下一篇文章中,我们将该窗口转换为Unity自己的控制台窗口的克隆。


那么,让我们开始吧!首先,我们将创建一个空的Unity项目,并在Assets下添加一个名为Editor的文件夹。如果您在Unity中为文件夹指定某些名称,它将以特殊方式处理其内容。编辑器就是其中一个名称,此文件夹中的脚本将成为Unity自己编辑器的一部分。那么,让我们构建一个编辑器窗口脚本:进入刚刚创建的Editor文件夹,右键单击,然后选择Create - > C#Script。您也可以选择Editor Test C#Script,但我们会改变所有内容,所以它实际上并不重要。将脚本命名为ResizablePanels,然后在您喜欢的文本编辑器中打开它(在Gram Games中我们更喜欢Xamarin)。


由于这将是一个编辑器窗口,因此该类应该来自EditorWindow而不是MonoBehaviour。 EditorWindow类驻留在UnityEditor命名空间中,因此我们也需要添加它。

using UnityEngine;
using UnityEditor;
public class ResizablePanels : EditorWindow
{
}


编辑器窗口需要初始化静态方法。 在这个方法中,我们将构建窗口并(可选)给它一个标题。 GetWindow()是一个EditorWindow方法,它创建窗口(如果它不存在),或者查找并关注它(如果存在)。


但是,静态方法本身是不够的,我们还需要添加一个按钮或类似的东西,让我们的用户在Unity中打开窗口。 值得庆幸的是,已经有一个名为MenuItem的属性,它将一个菜单项添加到Unity的菜单栏并运行它应用的方法。 因此,以下代码将创建您可以在Unity中创建的最基本的编辑器窗口。

using UnityEngine;
using UnityEditor;
public class ResizablePanels : EditorWindow
{
[ MenuItem( "Window/Resizable Panels")]
private static void OpenWindow()
{
ResizablePanels window = GetWindow< ResizablePanels>();
window. titleContent = new GUIContent( "Resizable Panels");
}
}


这是菜单项:


这是我们点击它时打开的窗口:


为了在这个窗口中绘图,我们将使用OnGUI()方法(是的,Unity自己的编辑器系统仍然使用旧的GUI系统,它可能不会长时间改变)。但首先,我们需要两个矩形来定义我们的面板。我还将在他们自己的方法中绘制这些面板,所以当我们处理它时,我们也应该添加这些方法。

using UnityEngine;
using UnityEditor;
public class ResizablePanels : EditorWindow
{
private Rect upperPanel;
private Rect lowerPanel;
[ MenuItem( "Window/Resizable Panels")]
private static void OpenWindow()
{
ResizablePanels window = GetWindow< ResizablePanels>();
window. titleContent = new GUIContent( "Resizable Panels");
}
private void OnGUI()
{
DrawUpperPanel();
DrawLowerPanel();
}
private void DrawUpperPanel()
{
}
private void DrawLowerPanel()
{
}
}


我们的编辑窗口开始形成。我们现在需要做的就是绘制面板并检查它们是否正常工作。GUILayout.BeginArea(Rect rect)将创建一个要绘制的矩形区域,GUILayout.EndArea()标记结束。这些区域将定义我们的面板。我还要在这两个区域添加标签,以便我们可以看到它们的外观。

using UnityEngine;
using UnityEditor;
public class ResizablePanels : EditorWindow
{
private Rect upperPanel;
private Rect lowerPanel;
[ MenuItem( "Window/Resizable Panels")]
private static void OpenWindow()
{
ResizablePanels window = GetWindow< ResizablePanels>();
window. titleContent = new GUIContent( "Resizable Panels");
}
private void OnGUI()
{
DrawUpperPanel();
DrawLowerPanel();
}
private void DrawUpperPanel()
{
upperPanel = new Rect( 0, 0, position. width, position. height * 0.5f);
GUILayout. BeginArea( upperPanel);
GUILayout. Label( "Upper Panel");
GUILayout. EndArea();
}
private void DrawLowerPanel()
{
lowerPanel = new Rect( 0, position. height * 0.5f, position. width, position. height * 0.5f);
GUILayout. BeginArea( lowerPanel);
GUILayout. Label( "Lower Panel");
GUILayout. EndArea();
}
}


好吧,他们似乎在工作:


然而,这两个面板被设置为覆盖窗口的一半,但是如果我们希望它们可以调整大小,则它们需要具有可变高度。所以,我要添加一个大小比例变量; 这样,当一个面板覆盖一定量的窗口时,另一个面板可以覆盖剩余部分。

using UnityEngine;
using UnityEditor;
public class ResizablePanels : EditorWindow
{
private Rect upperPanel;
private Rect lowerPanel;
private float sizeRatio = 0.5f;
[ MenuItem( "Window/Resizable Panels")]
private static void OpenWindow()
{
ResizablePanels window = GetWindow< ResizablePanels>();
window. titleContent = new GUIContent( "Resizable Panels");
}
private void OnGUI()
{
DrawUpperPanel();
DrawLowerPanel();
}
private void DrawUpperPanel()
{
upperPanel = new Rect( 0, 0, position. width, position. height * sizeRatio);
GUILayout. BeginArea( upperPanel);
GUILayout. Label( "Upper Panel");
GUILayout. EndArea();
}
private void DrawLowerPanel()
{
lowerPanel = new Rect( 0, ( position. height * sizeRatio), position. width, position. height * ( 1 - sizeRatio));
GUILayout. BeginArea( lowerPanel);
GUILayout. Label( "Lower Panel");
GUILayout. EndArea();
}
}


好的,两个面板都有可变的高度......但是我们仍然无法调整它们的大小!但不要担心,我们离最终产品并不太远。现在我们只需要另一个矩形区域,这样当用户点击那里时我们就可以开始调整大小。我将在两个面板之间添加该区域。这将是10像素高,因为,为什么不呢?我喜欢10(我喜欢1010!甚至更好:))。

我们还需要向用户显示鼠标指针位于调整大小区域中。EditorGUIUtility.AddCursorRect(Rect rect,MouseCursor cursor)就是这样做的,所以我们将在绘图方法中使用它。

我们需要向用户展示另一件事:调整大小区域的开始位置。这看起来像魔术,但我保证,它不是:我们将使用Unity自己的一个图标并将其拉伸并放置,使其看起来像上下面板之间的线。

using UnityEngine;
using UnityEditor;
public class ResizablePanels : EditorWindow
{
private Rect upperPanel;
private Rect lowerPanel;
private Rect resizer;
private float sizeRatio = 0.5f;
private bool isResizing;
private GUIStyle resizerStyle;
[ MenuItem( "Window/Resizable Panels")]
private static void OpenWindow()
{
ResizablePanels window = GetWindow< ResizablePanels>();
window. titleContent = new GUIContent( "Resizable Panels");
}
private void OnEnable()
{
resizerStyle = new GUIStyle();
resizerStyle. normal. background = EditorGUIUtility. Load( "icons/d_AvatarBlendBackground.png") as Texture2D;
}
private void OnGUI()
{
DrawUpperPanel();
DrawLowerPanel();
DrawResizer();
}
private void DrawUpperPanel()
{
upperPanel = new Rect( 0, 0, position. width, position. height * sizeRatio);
GUILayout. BeginArea( upperPanel);
GUILayout. Label( "Upper Panel");
GUILayout. EndArea();
}
private void DrawLowerPanel()
{
lowerPanel = new Rect( 0, ( position. height * sizeRatio) + 5, position. width, position. height * ( 1 - sizeRatio) - 5);
GUILayout. BeginArea( lowerPanel);
GUILayout. Label( "Lower Panel");
GUILayout. EndArea();
}
private void DrawResizer()
{
resizer = new Rect( 0, ( position. height * sizeRatio) - 5f, position. width, 10f);
GUILayout. BeginArea( new Rect( resizer. position + ( Vector2. up * 5f), new Vector2( position. width, 2)), resizerStyle);
GUILayout. EndArea();
EditorGUIUtility. AddCursorRect( resizer, MouseCursor. ResizeVertical);
}
}


就快结束了:


现在,我们将通过添加实际的交互来最终确定它。我们将处理传入的事件,如果事件是鼠标按下事件并且它在调整大小区域,我们将开始调整大小。

using UnityEngine;
using UnityEditor;
public class ResizablePanels : EditorWindow
{
private Rect upperPanel;
private Rect lowerPanel;
private Rect resizer;
private float sizeRatio = 0.5f;
private bool isResizing;
private GUIStyle resizerStyle;
[ MenuItem( "Window/Resizable Panels")]
private static void OpenWindow()
{
ResizablePanels window = GetWindow< ResizablePanels>();
window. titleContent = new GUIContent( "Resizable Panels");
}
private void OnEnable()
{
resizerStyle = new GUIStyle();
resizerStyle. normal. background = EditorGUIUtility. Load( "icons/d_AvatarBlendBackground.png") as Texture2D;
}
private void OnGUI()
{
DrawUpperPanel();
DrawLowerPanel();
DrawResizer();
ProcessEvents( Event. current);
if ( GUI. changed) Repaint();
}
private void DrawUpperPanel()
{
upperPanel = new Rect( 0, 0, position. width, position. height * sizeRatio);
GUILayout. BeginArea( upperPanel);
GUILayout. Label( "Upper Panel");
GUILayout. EndArea();
}
private void DrawLowerPanel()
{
lowerPanel = new Rect( 0, ( position. height * sizeRatio) + 5, position. width, position. height * ( 1 - sizeRatio) - 5);
GUILayout. BeginArea( lowerPanel);
GUILayout. Label( "Lower Panel");
GUILayout. EndArea();
}
private void DrawResizer()
{
resizer = new Rect( 0, ( position. height * sizeRatio) - 5f, position. width, 10f);
GUILayout. BeginArea( new Rect( resizer. position + ( Vector2. up * 5f), new Vector2( position. width, 2)), resizerStyle);
GUILayout. EndArea();
EditorGUIUtility. AddCursorRect( resizer, MouseCursor. ResizeVertical);
}
private void ProcessEvents( Event e)
{
switch ( e. type)
{
case EventType. MouseDown:
if ( e. button == 0 && resizer. Contains( e. mousePosition))
{
isResizing = true;
}
break;
case EventType. MouseUp:
isResizing = false;
break;
}
Resize( e);
}
private void Resize( Event e)
{
if ( isResizing)
{
sizeRatio = e. mousePosition. y / position. height;
Repaint();
}
}
}


这是最终版本:


猜你喜欢

转载自blog.csdn.net/qq_31967569/article/details/81025888