一:EditorWindow类

Editor类和EditorWindow类都继承自同一个基类:ScriptableObject,他们都可以针对某种脚本类来进行操作

EditorWindow类主要是对编辑器进行扩展,不需要指定脚本,是绘制独立的窗口

使用到的类:

——GUILayout:绘制各种2D控件,比如按钮、文本、可折叠列表,以及对它们的分组和排版。这些控件既可以绘制在Editor类里,也可以绘制在EditorWindow里

——EditorGUILayout:与GUILayout类似,但是提供更多的预定义控件

——GUIUtility:绘制自定义的2D控件,比如进度条、对话框、打开文件夹

——EditorGUIUtility:绘制自定义的2D控件,比如进度条、对话框、打开文件夹

重写OnGUI方法进行绘制


二:代码实现

——窗口Window

Unity编辑器扩展——自定义窗口_滑动条Unity编辑器扩展——自定义窗口_字段_02

[MenuItem("工具栏层级")]
private static void ShowWindow()
{
//第一种
EditorWindow window = GetWindow(typeof(TestWindow), true, "测试窗口");
//第二种
EditorWindow window = CreateWindow<Cheat>("测试窗口");

window.Show();
window.Focus();
}

——标签Label

Unity编辑器扩展——自定义窗口_控件_03

private void OnGUI()
{
GUI.skin.label.fontSize = 20;
GUI.skin.label.fontStyle = FontStyle.Bold;
GUI.skin.label.alignment = TextAnchor.MiddleCenter;
GUILayout.Label("测试窗口");
GUILayout.Label(Resources.Load<Texture>("Resources文件夹下的图片路径"));
}


Project目录下右键—Create—GUI Skin可以看到所有可修改的属性
Unity编辑器扩展——自定义窗口_字段_04


——文本字段TextField

Unity编辑器扩展——自定义窗口_滑动条_05

string txt;

private void OnGUI()
{
txt = EditorGUILayout.TextField("输入文本:", txt);
}

——密码字段PasswordField

Unity编辑器扩展——自定义窗口_控件_06

string txt;

private void OnGUI()
{
txt = EditorGUILayout.PasswordField("密码:", txt);

}

——整数字段IntField、浮点数字段FloatField

Unity编辑器扩展——自定义窗口_字段_07

int value_int;
float value_float;

private void OnGUI()
{
value_int = EditorGUILayout.IntField("输入整数:", value_int);
value_float = EditorGUILayout.FloatField("输入浮点数:", value_float);
}

——二维向量字段Vector2Field、三维向量字段Vector3Field

Unity编辑器扩展——自定义窗口_字段_08

private Vector3 v3;
private Vector3 v2;

private void OnGUI()
{
v3 = EditorGUILayout.Vector3Field("三维向量", v3);
v2 = EditorGUILayout.Vector2Field("二维向量", v2);
}

——物体字段ObjectField

Unity编辑器扩展——自定义窗口_字段_09

GameObject go;
Camera camera;

private void OnGUI()
{
go = (GameObject)EditorGUILayout.ObjectField("赋值物体", go, typeof(GameObject), true);
camera = (Camera)EditorGUILayout.ObjectField("赋值相机", camera, typeof(Camera), true);
}

——颜色字段ColorField

Unity编辑器扩展——自定义窗口_控件_10

private Color color;

private void OnGUI()
{
color = EditorGUILayout.ColorField("颜色", color);
}

——标签字段TagField

Unity编辑器扩展——自定义窗口_控件_11

private string tag;

private void OnGUI()
{
tag = EditorGUILayout.TagField("tag", tag);
}

——层级字段LayerField

Unity编辑器扩展——自定义窗口_控件_12

private int layer;

private void OnGUI()
{
layer = EditorGUILayout.LayerField("layer", layer);
}

——按钮Button

Unity编辑器扩展——自定义窗口_控件_13

private void OnGUI()
{
if (GUILayout.Button("按钮"))
{
//按下按钮后执行的方法
}
}

——多行文本TextArea

Unity编辑器扩展——自定义窗口_滑动条_14

string txt;

private void OnGUI()
{
GUILayout.BeginHorizontal();
GUILayout.Label("输入文本:",GUILayout.MaxWidth(50));
txt = EditorGUILayout.TextArea(txt, GUILayout.MaxHeight(50));
GUILayout.EndHorizontal();
}

——单选框Toggle

Unity编辑器扩展——自定义窗口_控件_15

bool b;

private void OnGUI()
{
b = EditorGUILayout.Toggle("单选框", b);
}

——折叠列表Foldout

Unity编辑器扩展——自定义窗口_字段_16

bool foldout;

private void OnGUI()
{
foldout= EditorGUILayout.Foldout(foldout, "列表");
if (foldout)
{
EditorGUILayout.LabelField("姓名:XXX");
EditorGUILayout.LabelField("手机号:XXXXXXXXXXX");
EditorGUILayout.LabelField("微信:XXXXXXXX");
}
}

——开关组BeginToggleGroup/EndToggleGroup

Unity编辑器扩展——自定义窗口_滑动条_17Unity编辑器扩展——自定义窗口_滑动条_18

GameObject go;
string txt;
bool b;

private void OnGUI()
{
b = EditorGUILayout.BeginToggleGroup("开启区域", b);
txt = EditorGUILayout.TextField("输入文本:", txt);
go = (GameObject)EditorGUILayout.ObjectField("赋值物体", go, typeof(GameObject), true);
EditorGUILayout.EndToggleGroup();
}

——可选择文本SelectableLabel(用于需要复制的文本)

Unity编辑器扩展——自定义窗口_滑动条_19

private void OnGUI()
{
EditorGUILayout.SelectableLabel("微信号:597094538");
}

——滑动条Slider、整数滑动条IntSlider

Unity编辑器扩展——自定义窗口_字段_20

int value_int;
float value_float;

private void OnGUI()
{
value_float = EditorGUILayout.Slider("滑动条", value_float, 1, 10);
value_int = EditorGUILayout.IntSlider("滑动条", value_int, 1, 10);
}

——字符串类型的弹出选择菜单Popup

Unity编辑器扩展——自定义窗口_字段_21

private int index = 0;
string[] values = { "value1", "value2", "value3" };

private void OnGUI()
{
index = EditorGUILayout.Popup("选择", index, values);
}

——枚举类型的弹出选择菜单EnumPopup

Unity编辑器扩展——自定义窗口_滑动条_22

public enum Value
{
Value1,
Value2,
Value3,
}
private Value value;


private void OnGUI()
{
value = (Value)EditorGUILayout.EnumPopup("选择", value);
}

——整数类型的弹出选择菜单IntPopup

Unity编辑器扩展——自定义窗口_字段_23

private int index = 0;
string[] values = { "value1", "value2", "value3" };
int[] value = { 1, 2, 3 };

private void OnGUI()
{
index = EditorGUILayout.IntPopup("选择", index, values, value);
EditorGUILayout.LabelField("value是:" + index);
}

——设置绘制的方向BeginScrollView、EndHorizontal和BeginVertical、EndVertical

BeginScrollView和BeginVertical可以设置内置样式

Unity编辑器扩展——自定义窗口_字段_24

private void OnGUI()
{
EditorGUILayout.BeginHorizontal();

EditorGUILayout.EndHorizontal();
}

——设置滑动区域BeginScrollView、EndScrollView

Unity编辑器扩展——自定义窗口_字段_25

Vector2 scrollPos;

private void OnGUI()
{
scrollPos = EditorGUILayout.BeginScrollView(scrollPos);

EditorGUILayout.EndScrollView();
}

——再次确认的对话框DisplayDialog

Unity编辑器扩展——自定义窗口_滑动条_26

private void OnGUI()
{
if (GUILayout.Button("按钮", GUILayout.Width(50), GUILayout.Height(50)))
{
if (EditorUtility.DisplayDialog("再次确定", "是否确定", "确定", "取消"))
{
Debug.Log("yes");
}
}
}

——进度条DisplayProgressBar

Unity编辑器扩展——自定义窗口_滑动条_27

private void OnGUI()
{
if (GUILayout.Button("按钮"))
{
int totalCount = Selection.gameObjects.Length;
for (int i = Selection.gameObjects.Length - 1; i >= 0; i--)
{
DestroyImmediate(Selection.gameObjects[i]);
EditorUtility.DisplayProgressBar("进度条", "当前进度", totalCount - i / totalCount);
}
EditorUtility.ClearProgressBar();
}
}

——工具栏Toolbar

Unity编辑器扩展——自定义窗口_字段_28Unity编辑器扩展——自定义窗口_控件_29

string[] values = { "Menu1", "Menu2", "Menu3" };
private int index = 0;
//string[] values = { "value1", "value2", "value3" };

private void OnGUI()
{
index = GUILayout.Toolbar(index, values);
if (index == 0)
{
EditorGUILayout.LabelField("this is menu1");
}
else if (index == 1)
{
EditorGUILayout.LabelField("this is menu2");
}
}

——显示提示信息ShowNotification

Unity编辑器扩展——自定义窗口_滑动条_30

private void OnGUI()
{
if (GUILayout.Button("显示提示信息"))
{
ShowNotification(new GUIContent("this is a Notification"));
}
if (GUILayout.Button("关闭提示信息"))
{
RemoveNotification();
}
}

——显示帮助信息HelpBox

Unity编辑器扩展——自定义窗口_字段_31

private void OnGUI()
{
EditorGUILayout.HelpBox("帮助信息", MessageType.None);
EditorGUILayout.HelpBox("警告提示", MessageType.Warning);
}

——选择文件/文件夹位置

Unity编辑器扩展——自定义窗口_滑动条_32

private void OnGUI()
{
if (GUILayout.Button("选择存储位置"))
{
path = EditorUtility.OpenFilePanel("选择文件", path, ".xls");
dir = EditorUtility.OpenFolderPanel("选择路径", dir, "");
}
}

三:绘制一个自定义的Debug窗口

Unity编辑器扩展——自定义窗口_字段_33

using UnityEditor;
using UnityEngine;
using UnityEngine.SceneManagement;
using System.IO;

public class DebugWindow : EditorWindow
{
[MenuItem("Tools/Show DebugWindow")]
private static void ShowWindow()
{
GetWindow(typeof(DebugWindow), true, "Debug窗口", true);
}

int toolbarIndex;
string[] toolbarStr = { "Error反馈窗口", "Warning反馈窗口" };

bool haveError;
bool haveErrorDes;
string errorName;
GameObject errorGo;
string errorDes;
string[] errorType = { "普通", "一般", "严重" };
private int errorTypeIndex;
string errorPath;

private void OnGUI()
{
toolbarIndex = GUILayout.Toolbar(toolbarIndex, toolbarStr);
if (toolbarIndex == 0)
{
//标题标签
GUI.skin.label.fontSize = 20;
GUI.skin.label.fontStyle = FontStyle.Bold;
GUI.skin.label.alignment = TextAnchor.MiddleCenter;
GUILayout.Label("Error反馈窗口");

haveError = EditorGUILayout.Toggle("是否有Error", haveError);
if (haveError)
{
//问题名
errorName = EditorGUILayout.TextField("问题名", errorName);
if (errorName != null)
{
if (errorName.Length == 0 || errorName == "")
{
EditorGUILayout.HelpBox("问题名不能为空", MessageType.Error);
}
else if (errorName.Length >= 5)
{
EditorGUILayout.HelpBox("问题名过长", MessageType.Warning);
}
else
{
EditorGUILayout.HelpBox("问题名合法", MessageType.Info);
}
}

//出现问题的时间
EditorGUILayout.LabelField("当前时间", System.DateTime.Now.ToString());

//出现问题的场景
EditorGUILayout.LabelField("当前场景", SceneManager.GetActiveScene().name);

//出现问题的物体
errorGo = (GameObject)EditorGUILayout.ObjectField("问题物体", errorGo, typeof(GameObject), true);

//问题描述
haveErrorDes = EditorGUILayout.BeginToggleGroup("是否添加问题描述", haveErrorDes);
EditorGUILayout.BeginHorizontal();
EditorGUILayout.LabelField("问题描述:", GUILayout.MaxWidth(50));
EditorGUILayout.TextArea(errorDes, GUILayout.MaxHeight(50));
EditorGUILayout.EndHorizontal();
EditorGUILayout.EndToggleGroup();

//问题类型
errorTypeIndex = EditorGUILayout.Popup("问题类型", errorTypeIndex, errorType);

//问题保存路径
EditorGUILayout.BeginHorizontal();
if (GUILayout.Button("选择路径"))
{
errorPath = EditorUtility.SaveFolderPanel("Path to Save", errorPath, Application.dataPath);
}
EditorGUILayout.TextField(errorPath);
EditorGUILayout.EndHorizontal();

GUILayout.Space(50);

//保存到本地
if (GUILayout.Button("保存"))
{
if (errorPath == null)
{
ShowNotification(new GUIContent("请先选择保存路径"), 1);
}
else
{
Directory.CreateDirectory(errorPath + "/BugReports");
StreamWriter sw = new StreamWriter(errorPath + "/BugReports/" + errorName + ".txt");
sw.WriteLine("Error or Warning:" + toolbarStr[toolbarIndex]);
sw.WriteLine("问题名:" + errorName);
sw.WriteLine("出现问题的时间:" + System.DateTime.Now.ToString());
sw.WriteLine("出现问题的场景:" + SceneManager.GetActiveScene().name);
sw.WriteLine("问题描述:" + errorDes);
sw.WriteLine("问题类型:" + errorType);
sw.WriteLine("问题存储路径:" + errorPath);
sw.Close();
}
}
}
}
else if (toolbarIndex == 1)
{
GUI.skin.label.fontSize = 20;
GUI.skin.label.fontStyle = FontStyle.Bold;
GUI.skin.label.alignment = TextAnchor.MiddleCenter;
GUILayout.Label("Warning反馈窗口");

//其他的与Error反馈窗口基本相同
}
}
}