什么是UI系统
Ul是UserInterface(用户界面)的简称
系统的主要学习内容
1.UI控件的使用
2.U控件的事件响应
3.U的分辨率自适应
文章目录
- 基础知识
- 1、工作原理和主要作用
- 2、基本控件
- 1、文本和按钮控件
- 2、多选框和单选框
- 3、输入框和拖动条
- 4、图片绘制和框
- 3、复合控件
- 1、工具栏和选择网格
- 2、滚动视图和分组
- 3、窗口相关
- 4、自定义整体样式
- 1、GUIskin
- 2、GUILayout
- 实践小项目
- 1、需求分析
- 2、九宫格布局概念
- 3、控件位置信息类
- 4、控件父类
- 5、父对象控制绘制顺序
- 6、自定义常用控件
- 1、自定义文本和按钮
- 2、自定义多选框
- 3、自定义多选框控件(单选)
- 4、自定义输入框和拖动条
- 5、自定义图片绘制
基础知识
1、工作原理和主要作用
1、GUI概念
即时模式游戏用户交互界面(IMGUI)
在Unity简称GUI
它是一个代码驱动的UI系统
2、GUI作用
1,作为程员的调试,创建游戏内调试身
2.为脚本组件创建自定义检视面板
3.创建新的编辑器窗口和工具以拓展Unity本身(一般用作内置游戏工具)
3、GUI的工作原理
在继承MonoBehaviour的脚本中的特殊函数里
调用GUI提供的方法,类似生命周期函数
private void OnGUI()
{
//在其中书写GUI相关代码即可显示GUI内容
}
注意:
1.它每顿热行相当于是用于专门绘制GUI界面的函数
2:一般只在其中执行GUI相关界面绘制和操作逻辑
3.该函数在【OnDisable】之前【LateUpdate】之后执行
4.只要是继承Mono的脚本都可以在OnGUI中绘制GUI
2、基本控件
1、文本和按钮控件
1、GUI控件绘制的共同点
1.他们都是GUI公共类中提供的静态函数,直接调用即可
2.他们的参数都大同小异
位置参数:Rect参数 x y位置 w h尺寸
显示文本:string参数
图片信息:Texture参数
综合信息:GUIContent参数
自定义样式:GUIStyle参数
3.每一种控件都有多种重载,都是各个参数的排列组合
必备的参数内容是【位置信息】和【显示信息】
2、文本控件
public Rect rect; //位置
public Texture text; //图片
public GUIContent content; //综合使用
public GUIStyle style; //自定义样式
private void OnGUI()
{
1、基本使用
GUI.Label(new Rect(0, 0, 100, 20), "文本控件");
GUI.Label(rect, text);
2、综合使用 (左图,右文字)
GUI.Label(rect, content);
3、获取GUI控件对应的信息
Debug.Log(GUI.tooltip);
4、自定义样式
GUI.Label(new Rect(0, 0, 100, 20), "文本控件", style);
字体路径 C:\Windows\Fonts
}
3、按钮控件
public Rect btnRect;
public GUIContent btnContent;
public GUIStyle btnStyle;
private void OnGUI()
{
if(GUI.Button(btnRect, btnContent, btnStyle))
//Button 按下抬起算一次点击
//RepeatButton 长按,一直返回true
{
Debug.Log("按钮被点击");
}
}
2、多选框和单选框
1、多选框
普通样式
private bool isSel;
private void OnGUI()
{
isSel = GUI.Toggle(new Rect(0, 0, 100, 30), isSel, "效果开关");
}
自定义样式
修改固定宽高 fixedWidth 和 fixedHeight
修改从GUIStyle边缘到内容起始处的空间 padding
2、单选框
private int nowSelIndex = 1;
private void OnGUI()
{
//Toggle点击后返回true
if(GUI.Toggle(new Rect(0, 100, 100, 20), nowSelIndex == 1, "选项一"))
nowSelIndex = 1;
if (GUI.Toggle(new Rect(0, 140, 100, 20), nowSelIndex == 2, "选项二"))
nowSelIndex = 2;
if (GUI.Toggle(new Rect(0, 180, 100, 20), nowSelIndex == 3, "选项三"))
nowSelIndex = 3;
}
3、输入框和拖动条
1、输入框
普通输入
private string inputStr;
private void OnGUI()
{
//5为最大输入长度
inputStr = GUI.TextField(new Rect(0, 0, 100, 30), inputStr,5);
}
密码输入
private string inputPW;
private void OnGUI()
{
inputPW = GUI.PasswordField(new Rect(0, 0, 100, 30), inputPW, '*');
}
2、拖动条
水平拖动条
private float nowValue = 0.5f;
private void OnGUI()
{
nowValue = GUI.HorizontalSlider(new Rect(0, 100, 100, 50), nowValue, 0, 1);
}
竖直拖动条
nowValue = GUI.VerticalSlider(new Rect(0, 150, 50, 100), nowValue, 0, 1);
4、图片绘制和框
1、图片绘制
public Rect texPos;
public Texture tex;
public ScaleMode mode; //显示模式
//ScaleAndCrop: 通过宽高裁剪
//ScaleToFit: 缩放不会变形
//ScaleToFill: 填充满宽高(默认)
public bool alpha; //背景是否透明
private void OnGUI()
{
GUi.DrawTexture(texPos, tex, mode, alpha);
}
2、框绘制
GUI.Box(texPos, "");
3、复合控件
1、工具栏和选择网格
1、工具栏
private int toolbarIndex = 0;
private string[] toolbarInfos = new string[] { "选项一", "选项二", "选项三" };
private void OnGUI()
{
toolbarIndex = GUI.Toolbar(new Rect(0, 0, 200, 30), toolbarIndex, toolbarInfos);
}
private void DrawWindow(int id)
{
switch (id)
{
case 1:
GUI.Button(new Rect(0, 30, 30, 20), "按钮1");
break;
case 2:
GUI.Button(new Rect(0, 30, 30, 20), "按钮2");
break;
case 3:
GUI.DragWindow();
break;
}
}
2、选择网格
private int selGridIndex = 0;
private void OnGUI()
{
//xCount 水平方向最多显示数量,超过的另起一行
selGridIndex = GUI.SelectionGrid(new Rect(0, 50, 200, 90), selGridIndex, toolbarInfos, 1);
}
2、滚动视图和分组
1、分组
用于批量控制空间位置
public Rect groupPos;
private void OnGUI()
{
GUI.BeginGroup(groupPos);
GUI.Button(new Rect(0, 0, 100, 50), "按钮");
GUI.Label(new Rect(0, 60, 100, 20), "Lable");
GUI.EndGroup();
}
2、滚动列表
public Rect scPos; //可视范围
public Rect showPos; //内容
private Vector2 nowPos;
private string[] strs = new string[] { "选项一", "选项二", "选项三" };
private void OnGUI()
{
nowPos = GUI.BeginScrollView(scPos, nowPos, showPos);
GUI.Toolbar(new Rect(0, 0, 300, 50), 0, strs);
GUI.EndScrollView();
}
3、窗口相关
1、窗口
private void DrawWindow(int id)
{
GUI.Button(new Rect(0, 30, 30, 20), "按钮");
}
private void OnGUI()
{
//参数1:id
GUI.Window(1, new Rect(100, 100, 200, 150), DrawWindow, "窗口");
}
2、模态窗口
优先处理窗口(警告窗口)
GUI.ModalWindow(2, new Rect(100, 100, 200, 150), DrawWindow, "模态窗口");
3、拖动窗口
dragWinPos = GUI.Window(3, dragWinPos, DrawWindow, "窗口");
//参数用来设置可拖动位置
private void DrawWindow(int id)
{
GUI.DragWindow();
}
4、自定义整体样式
1、GUIskin
1、全局颜色
全局着色,影响背景和文本颜色
GUI.color = Color.red;
文本着色
GUI.contentColor = Color.yellow;
背景元素着色
GUI.backgroundColor = Color.red;
注意:会和全局颜色相乘
2、整体皮肤样式
public GUISkin skin;
GUI.skin = skin;
2、GUILayout
1、GUILayout 自动布局
GUILayout.BeginArea(new Rect(100,100,100,100)); //设置整体位置,宽高为可见范围
//GUI.BeginGroup(new Rect(100,100,100,100)); GUI综合使用
GUILayout.BeginHorizontal(); //水平布局
GUILayout.BUtton("按钮");
GUILayout.Endorizontal();
GUILayout.EndArea;
GUI.EndGroup();
2、GUILayoutOption 布局选项
GUILayout.BUtton("按钮",GUILayout.With(300));
控件的固定宽高
GUILayout.Width(300); GUILayout.Height(200);
充许控件的最小宽高
GuILayout.Minwidth(50); GuILayout.MinHeight(50));
充许控件的最大宽高
GuILayout.Maxwidth(100) GUILayout.MaxHeight(100));
充许或禁止水平拓展
GuILayout.Expandwidth(true); //允许
GUILayout.ExpandHeight(false); //禁止
GUILayout.ExpandHeight(true); //允许
GUILayout.ExpandHeight(false); //禁止
编辑模式下让指定代码运行
添加特性
[ExecuteAlways]
实践小项目
1、需求分析
1、位置信息类
位置信息类
中心点位置
偏移位置
宽高
最终位置
中心点对齐方式
屏幕对齐方式
2、控件基类
控件基类
位置信息
内容信息
自定义样式
是否开启自定义样式
2、九宫格布局概念
九宫格原点:
左上(0,0) 上(w/2,0) 右上(w,0)
左(0,h/2) 中(w/2,h/2) 右(w,h/2)
左下(0,h) 下(w/2,h) 右下(w,h)
控件位置:
(0,0) (-cw/2,0) (-cw,0)
(0,-ch/2) (-cw/2,-ch/2) (-cw,-ch/2)
(0,-ch) (-cw/2,-ch) (-cw,-ch)
控件坐标计算公式:
相对屏幕位置 + 中心点偏移位置 + 偏移位置
3、控件位置信息类
CustomGUIPos
using UnityEngine;
public enum E_Alignment_Type
{
Up, Down, Left, Right,
Center,
Left_Up, Left_Down, Right_Up, Right_Down,
}
public class CustomGUIPos
{
private Rect rpos = new Rect(0, 0, 100, 100);
//屏幕九宫格对齐方式
public E_Alignment_Type screen_Alignment_Type;
//控件中心对齐方式
public E_Alignment_Type control_Center_Alignment_Type;
//偏移位置
public Vector2 pos;
//控件宽高
public float width = 100;
public float height = 50;
//中心点
private Vector2 centerPos;
//控件中心点偏移位置
private void CalcCenterPos()
{
switch (control_Center_Alignment_Type)
{
case E_Alignment_Type.Up:
centerPos.x = -width / 2;
centerPos.y = 0;
break;
case E_Alignment_Type.Down:
centerPos.x = -width / 2;
centerPos.y = -height;
break;
case E_Alignment_Type.Left:
centerPos.x = 0;
centerPos.y = -height / 2;
break;
case E_Alignment_Type.Right:
centerPos.x = -width;
centerPos.y = -height / 2;
break;
case E_Alignment_Type.Center:
centerPos.x = -width / 2;
centerPos.y = -height / 2;
break;
case E_Alignment_Type.Left_Up:
centerPos.x = 0;
centerPos.y = 0;
break;
case E_Alignment_Type.Left_Down:
centerPos.x = 0;
centerPos.y = -height;
break;
case E_Alignment_Type.Right_Up:
centerPos.x = -width;
centerPos.y = 0;
break;
case E_Alignment_Type.Right_Down:
centerPos.x = -width;
centerPos.y = -height;
break;
}
}
//最终位置
private void CalcPos()
{
switch (screen_Alignment_Type)
{
case E_Alignment_Type.Up:
//相对屏幕位置 + 中心点偏移位置 + 偏移位置
rpos.x = Screen.width / 2 + centerPos.x + pos.x;
rpos.y = 0 + centerPos.y + pos.y;
break;
case E_Alignment_Type.Down:
rpos.x = Screen.width / 2 + centerPos.x + pos.x;
rpos.y = Screen.height + centerPos.y - pos.y;
break;
case E_Alignment_Type.Left:
rpos.x = 0 + centerPos.x + pos.x;
rpos.y = Screen.height / 2 + centerPos.y + pos.y;
break;
case E_Alignment_Type.Right:
rpos.x = Screen.width + centerPos.x - pos.x;
rpos.y = Screen.height / 2 + centerPos.y + pos.y;
break;
case E_Alignment_Type.Center:
rpos.x = Screen.width / 2 + centerPos.x + pos.x;
rpos.y = Screen.height / 2 + centerPos.y + pos.y;
break;
case E_Alignment_Type.Left_Up:
rpos.x = centerPos.x + pos.x;
rpos.y = centerPos.y + pos.y;
break;
case E_Alignment_Type.Left_Down:
rpos.x = centerPos.x + pos.x;
rpos.y = Screen.height + centerPos.y - pos.y;
break;
case E_Alignment_Type.Right_Up:
rpos.x = Screen.width + centerPos.x - pos.x;
rpos.y = centerPos.y + pos.y;
break;
case E_Alignment_Type.Right_Down:
rpos.x = Screen.width + centerPos.x - pos.x;
rpos.y = Screen.height + centerPos.y - pos.y;
break;
}
}
public Rect Pos
{
get
{
//计算中心点偏移
CalcCenterPos();
//相对屏幕坐标点
CalcPos();
//修改控件的宽高
rpos.width = width;
rpos.height = height;
return rpos;
}
}
}
4、控件父类
CustomGUIControl
using UnityEngine;
public enum E_style_OnOff
{
On,Off,
}
public class CustomGUIControl : MonoBehaviour
{
//位置信息
public CustomGUIPos guiPos;
//显示内容信息
public GUIContent content;
//自定义样式
public GUIStyle style;
//自定义样式开关
public E_style_OnOff styleOn_or_Off = E_style_OnOff.Off;
private void OnGUI()
{
switch (styleOn_or_Off)
{
case E_style_OnOff.On:
StyleOnDraw();
break;
case E_style_OnOff.Off:
StyleOffDraw();
break;
}
}
protected virtual void StyleOnDraw()
{
//GUI.Button(guiPos.Pos, content, style);
}
protected virtual void StyleOffDraw()
{
//GUI.Button(guiPos.Pos, content);
}
}
5、父对象控制绘制顺序
修改CustomGUIControl
//public void OnGUI()修改为
public void DrawGUI(){}
CustomGUIRoot
using UnityEngine;
[ExecuteAlways] //编辑模式下能看到GUI
public class CustomGUIRoot : MonoBehaviour
{
//存储子对象所有的GUI控件的容器
private CustomGUIControl[] allControls;
void Start()
{
allControls = this.GetComponentsInChildren<CustomGUIControl>();
}
//同一绘制子对象控件
private void OnGUI()
{
if (!Application.isPlaying)
{
//得到父类脚本
allControls = this.GetComponentsInChildren<CustomGUIControl>();
}
//可以控件控件的绘制顺序
for (int i = 0; i < allControls.Length; i++)
{
//绘制每个控件
allControls[i].DrawGUI();
}
}
}
6、自定义常用控件
1、自定义文本和按钮
CustomGUILable
using UnityEngine;
public class CustomGUILable : CustomGUIControl
{
protected override void StyleOffDraw()
{
GUI.Label(guiPos.Pos, content);
}
protected override void StyleOnDraw()
{
GUI.Label(guiPos.Pos, content, style);
}
}
CustomGUIButton
using UnityEngine;
using UnityEngine.Events;
public class CustomGUIButton : CustomGUIControl
{
public event UnityAction clickEvent;
protected override void StyleOffDraw()
{
if (GUI.Button(guiPos.Pos,content))
{
clickEvent?.Invoke();
}
}
protected override void StyleOnDraw()
{
if (GUI.Button(guiPos.Pos, content, style))
{
clickEvent?.Invoke();
}
}
}
2、自定义多选框
CustomGUIToggle
using UnityEngine;
using UnityEngine.Events;
public class CustomGUIToggle : CustomGUIControl
{
public bool isSel;
public event UnityAction<bool> changeValue;
private bool isOldSel;
protected override void StyleOffDraw()
{
isSel = GUI.Toggle(guiPos.Pos, isSel, content);
if(isOldSel != isSel )
{
changeValue?.Invoke(isSel);
isOldSel = isSel;
}
}
protected override void StyleOnDraw()
{
isSel = GUI.Toggle(guiPos.Pos, isSel, content, style);
if (isOldSel != isSel)
{
changeValue?.Invoke(isSel);
isOldSel = isSel;
}
}
}
3、自定义多选框控件(单选)
CustomGUIToggleGroup
using UnityEngine;
public class CustomGUIToggleGroup : MonoBehaviour
{
public CustomGUIToggle[] toggles;
private CustomGUIToggle frontTrueTog;
void Start()
{
if (toggles.Length == 0)
return;
for (int i = 0; i < toggles.Length; i++)
{
CustomGUIToggle toggle = toggles[i];
toggle.changeValue += (value) =>
{
if(value)
{
for (int j = 0; j < toggles.Length; j++)
{
//其他的变false
if (toggles[j] != toggle)
{
toggles[j].isSel = false;
}
}
frontTrueTog = toggle;
}
else if (toggle == frontTrueTog)
{
toggle.isSel = true;
}
};
}
}
}
4、自定义输入框和拖动条
CustomGUIInput
using UnityEngine;
using UnityEngine.Events;
public class CustomGUIInput : CustomGUIControl
{
public event UnityAction<string> textChange;
private string oldStr = "";
protected override void StyleOffDraw()
{
content.text = GUI.TextField(guiPos.Pos,content.text);
if(oldStr != content.text)
{
textChange?.Invoke(oldStr);
oldStr = content.text;
}
}
protected override void StyleOnDraw()
{
content.text = GUI.TextField(guiPos.Pos, content.text, style);
if (oldStr != content.text)
{
textChange?.Invoke(oldStr);
oldStr = content.text;
}
}
}
CustomGUISlider
using UnityEngine;
using UnityEngine.Events;
public enum E_Slider_Type
{
Horizontal, //水平
Vertical, //竖直
}
public class CustomGUISlider : CustomGUIControl
{
public float minValue = 0;
public float maxValue = 1;
public float nowValue = 0;
public E_Slider_Type type = E_Slider_Type.Horizontal;
public GUIStyle styleThumb; //小按钮的style
public event UnityAction<float> changeValue;
private float oldValue = 0;
protected override void StyleOffDraw()
{
switch (type)
{
case E_Slider_Type.Horizontal:
nowValue = GUI.HorizontalSlider(guiPos.Pos, nowValue, minValue, maxValue);
break;
case E_Slider_Type.Vertical:
nowValue = GUI.VerticalSlider(guiPos.Pos, nowValue, minValue, maxValue);
break;
}
if (oldValue!=nowValue)
{
changeValue?.Invoke(nowValue);
oldValue = nowValue;
}
}
protected override void StyleOnDraw()
{
switch (type)
{
case E_Slider_Type.Horizontal:
nowValue = GUI.HorizontalSlider(guiPos.Pos, nowValue, minValue, maxValue, style, styleThumb);
break;
case E_Slider_Type.Vertical:
nowValue = GUI.VerticalSlider(guiPos.Pos, nowValue, minValue, maxValue, style, styleThumb);
break;
}
if (oldValue != nowValue)
{
changeValue?.Invoke(nowValue);
oldValue = nowValue;
}
}
}
5、自定义图片绘制
CustomGUITexture
using UnityEngine;
public class CustomGUITexture : CustomGUIControl
{
public ScaleMode scaleMode = ScaleMode.StretchToFill;
protected override void StyleOffDraw()
{
GUI.DrawTexture(guiPos.Pos,content.image, scaleMode);
}
protected override void StyleOnDraw()
{
GUI.DrawTexture(guiPos.Pos, content.image, scaleMode);
}
}