一 说明
- 脚本必须继承Editor,因此脚本无法绑定在场景中的某个物体
- 在Class前使用[CustomEditor(typeof(普通脚本组件名))],将当前脚本与场景中已经绑定的普通脚本类名相关联。这么设计的原因是继承了MonoBehiver的脚本是在runtime下运行的,如果想在editor条件下就运行则需要通过Editor绑定来扩展
- Editor可以放在Editor目录下,该目录不会随着游戏打包而输出。但有时编辑器对Editor类支持有故障时可以将其放在普通目录中解决问题。
- ui绘制代码需放在public override void OnInspectorGUI()周期中,并且需要在里面调用 DrawDefaultInspector();用于更新ui
二 Inspector高级ui组件的实现
2.1 需要引入的库
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System;
2.2 UI绘制函数
Inspector中的ui扩展应该写在OnInspectorGUI周期中,并调用DrawDefaultInspector来更新信息
public override void OnInspectorGUI()
{
// 刷新
DrawDefaultInspector();
....draw ui....
}
2.3 UI组件绘制
// slider、scrollbar的值
public float sliderValue;
// toggle的值
public bool toggleButtonValue;
// tab的index值
public int tabIndex = 0;
// text / passfiald的值
public string text;
// inspector ui刷新
public override void OnInspectorGUI()
{
// 刷新
DrawDefaultInspector();
// 获取目标脚本对象
MapCreator myScript = (MapCreator)target;
// ================== ui控件 ===========
// 直接在这里创建组件,会自动累加到MapCreator脚本组件的inspector面板的下方。
// 在组件参数中输入new Rect(0, 0, 300, 20)可以设置尺寸与位置
// GUILayout 和 gui的区别是一个是自动布局一个是绝对布局
// 创建默认尺寸按钮
if (GUILayout.Button("创建对象"))
{
// 将目标脚本的方法绑定到按钮的事件
myScript.BuildObject();
}
// layout的按钮
GUILayout.Button("I am completely inside an Area");
// 创建矩形提示盒
GUILayout.Box("Slider Value: " + Mathf.Round(sliderValue));
//创建 水平滑竿
sliderValue = GUILayout.HorizontalSlider(sliderValue, 0.0f, 10f);
// 垂直滑竿
sliderValue = GUILayout.VerticalSlider(sliderValue, 0.0f, 10f);
// 水平滚动条 值;滑竿的长度;最小值;最大值
sliderValue = GUILayout.HorizontalScrollbar(sliderValue, 5f, 0.0f, 10f);
// 垂直滚动条
sliderValue = GUILayout.VerticalScrollbar(sliderValue, 5f, 0.0f, 10f);
// 密码框
text = GUILayout.PasswordField(text, '*');
// label
GUILayout.Label("lable");
// 只要按住就会重复发送true的按钮
GUILayout.RepeatButton("holdon button");
// switch 开关
toggleButtonValue = GUILayout.Toggle(toggleButtonValue, "Toggle Button"))
// tab/单选按钮组/switch开关
string[] buttonNameList = {
"1", "2", "3", "4", "5", "6" };
switch (GUILayout.Toolbar(tabIndex, buttonNameList))
{
case 1:
// 使[]index为1的按钮处于按下的状态
tabIndex = 1;
break;
case 2:
tabIndex = 2;
break;
default:
break;
}
}
2.4 组件布局
2.4.1 定位布局和自动布局的区别
- 定位布局的组件位置由我们自己设定,相同位置的组件会相互覆盖,点击时会穿透所有控件同时出发
- 自动布局会自动排列位置,按水平或垂直group的设定排列在上一个控件后面
2.4.2 实现自动布局
使用GUILayout编写控件
通过调用bengin、end方法确定布局区域和垂直/水平方向
2.4.3 实现定位布局
使用GUI编写控件
或使用GUILayout,并输入Rect参数:例如GUILayout.BeginGroup(new Rect(0, 0, Screen.width, Screen.height));
public override void OnInspectorGUI()
{
// 刷新
DrawDefaultInspector();
// // 绝对布局,会覆盖在其他组件之上,并且在同一位置会穿透点击,自动布局会自动排列在物体后或下方
// GUILayout.BeginGroup(new Rect(0, 0, Screen.width, Screen.height));
// // (0,0)是群组的左上角
// // 创建框以便于知道群组在屏幕上的位置
// GUI.Box(new Rect(0, 0, Screen.width, Screen.height), "Group is here");
// GUILayout.Button(new Rect(20, 20, 30, 30), "Click me");
// // 结束前面开始的群组。这很重要,请记住!
// GUILayout.EndGroup();
//相对布局//自动布局
// GUILayout.BeginArea(new Rect(0, 0, 300, 300));
// GUILayout.Button("I am completely inside an Area");
// GUILayout.Button("I am not inside an Area");
// GUILayout.EndArea();
// 带有垂直/水平方案的布局 由于使用Rect所以自动布局也变成了绝对定位
GUILayout.BeginArea(new Rect(0, Screen.height - 330, 300, 300));
//开启垂直布局
GUILayout.BeginVertical();
// 嵌套第一个水平布局
GUILayout.BeginHorizontal();
GUILayout.Button("I am completely inside an Area");
GUILayout.Button("I am not inside an Area");
GUILayout.EndHorizontal();
// 嵌套第二个水平布局
GUILayout.BeginHorizontal();
GUILayout.Button("I am completely inside an Area");
GUILayout.Button("I am not inside an Area");
GUILayout.EndHorizontal();
GUILayout.EndVertical();
GUILayout.EndArea();
//设置面板高度
GUILayout.Space(300);
}
三 完整脚本
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System;
// 绑定目标脚本
[CustomEditor(typeof(TargetScriptName))]
public class MapCreatorEditor : Editor //必须继承Editor
{
// slider、scrollbar的值
public float sliderValue;
// toggle的值
public bool toggleButtonValue;
// tab的index值
public int tabIndex = 0;
// text / passfiald的值
public string text;
// inspector ui刷新
public override void OnInspectorGUI()
{
// 刷新
DrawDefaultInspector();
// 获取目标脚本对象
MapCreator myScript = (MapCreator)target;
// ================== ui控件
// 直接在这里创建组件,会自动累加到MapCreator脚本组件的inspector面板的下方。
// 在组件参数中输入new Rect(0, 0, 300, 20)可以设置尺寸与位置
// 创建默认尺寸按钮
if (GUILayout.Button("创建对象"))
{
// 将目标脚本的方法绑定到按钮的事件
myScript.BuildObject();
}
// layout的按钮
GUILayout.Button("I am completely inside an Area");
// 创建矩形提示盒
GUILayout.Box("Slider Value: " + Mathf.Round(sliderValue));
//创建 水平滑竿
sliderValue = GUILayout.HorizontalSlider(sliderValue, 0.0f, 10f);
// 垂直滑竿
sliderValue = GUILayout.VerticalSlider(sliderValue, 0.0f, 10f);
// 水平滚动条 值;滑竿的长度;最小值;最大值
sliderValue = GUILayout.HorizontalScrollbar(sliderValue, 5f, 0.0f, 10f);
// 垂直滚动条
sliderValue = GUILayout.VerticalScrollbar(sliderValue, 5f, 0.0f, 10f);
// 密码框
text = GUILayout.PasswordField(text, '*');
// label
GUILayout.Label("lable");
// 只要按住就会重复发送true的按钮
GUILayout.RepeatButton("holdon button");
// switch 开关
toggleButtonValue = GUILayout.Toggle(toggleButtonValue, "Toggle Button"))
// tab/单选按钮组/switch开关
string[] buttonNameList = {
"1", "2", "3", "4", "5", "6" };
switch (GUILayout.Toolbar(tabIndex, buttonNameList))
{
case 1:
// 使[]index为1的按钮处于按下的状态
tabIndex = 1;
break;
case 2:
tabIndex = 2;
break;
default:
break;
}
// ======================布局相关=========================
// GUILayout 和 gui的区别是一个是自动布局一个是绝对布局
// // 绝对布局,会覆盖在其他组件之上,并且在同一位置会穿透点击
// GUILayout.BeginGroup(new Rect(0, 0, Screen.width, Screen.height));
// // (0,0)是群组的左上角
// // 创建框以便于知道群组在屏幕上的位置
// GUI.Box(new Rect(0, 0, Screen.width, Screen.height), "Group is here");
// GUILayout.Button(new Rect(20, 20, 30, 30), "Click me");
// // 结束前面开始的群组。这很重要,请记住!
// GUILayout.EndGroup();
//相对布局//自动布局
// GUILayout.BeginArea(new Rect(0, 0, 300, 300));
// GUILayout.Button("I am completely inside an Area");
// GUILayout.Button("I am not inside an Area");
// GUILayout.EndArea();
// 带有垂直/水平方案的布局
GUILayout.BeginArea(new Rect(0, Screen.height - 330, 300, 300));
//开启垂直布局
GUILayout.BeginVertical();
// 嵌套第一个水平布局
GUILayout.BeginHorizontal();
// 窗口菜单模式,使用window字符 将内置一个窗口用于显示ui组件
GUILayout.BeginHorizontal("My Tools", "window", new[] {
GUILayout.Height(400), GUILayout.Width(100) });
GUILayout.Button("I am completely inside an Area");
GUILayout.Button("I am not inside an Area");
GUILayout.EndHorizontal();
// 嵌套第二个水平布局
GUILayout.BeginHorizontal();
//收尾
GUILayout.EndHorizontal();
GUILayout.EndVertical();
GUILayout.EndArea();
//设置面板高度
GUILayout.Space(300);
}
}