Unity3D学习笔记(4)——GUI基础

本章介绍GUI相关基础知识,使用老版UnityGUI进行测试。

本文仅供个人记录和复习,不用于其他用途

什么是GUI

举个简单的例子,像是游戏中的血条栏、经验栏等等,都是一直显示在游戏画面上的。不管是玩家走到哪里,或者杀了什么怪,这些元素都不会消失。因此,GUI 永远显示在屏幕上,不受光照、碰撞等因素影响。

平面坐标系

由于 GUI 是直接显示在屏幕上的,那么这里就不得不提一下坐标系了:

  • 屏幕坐标系是以屏幕左下角为(0, 0)点,右上角为(Screen.Width, Screen.Height)
  • 鼠标位置坐标系与屏幕坐标系一致
  • 视口(View Port)坐标是以摄像机为准,屏幕左下角为(0, 0),右上角为(1, 1)
  • 绘制 GUI 界面时使用的坐标是以屏幕的左上角为(0, 0)点,右下角为(Screen.Width, Screen.Height)

GUI 是以左上角为原点,其他的则是以左下角为原点,记住这一点即可。

OnGUI方法

UnityGUI曾经是官方的UI实现方法,不过 4.x 之后便推出了最新的uGUI系统,所以如果是要进行开发的话,还是推荐使用uGUI(之后会讲),这篇文章只用UnityGUI进行测试。UnityGUI提供了一个 OnGUI() 方法,OnGUI 会在每帧进行擦除、重绘,并实现相应的UI。下面来写一个简单的文本框:

1
2
3
void OnGUI() {
GUILayout.TextField("Hello World!", GUILayout.Width(100));
}

新建一个空的对象,将这个脚本连接到对象上后执行,效果如下:

那么这个文本框就会默认显示一段话Hello World!

OnGUI的擦除与重绘

虽然文本框是显示出来了,但当你真正去用它的时候就会有一个问题:不管你输入什么,文本框显示的内容都不变。

事实上,这涉及到了 OnGUI 方法的擦除与重绘。当你输入字符时,文本框确实是接收到了,但由于 OnGUI 每帧都会进行擦除,你所输入的内容便会在那一帧的结尾被去除掉,而下一帧所绘制的又将是默认的Hello World!。由于一秒有几十帧刷新,所以看起来就像是文本框没有收到输入内容。

看到这,想必你会有疑问,这种不停地擦除重绘有什么用?我又该如何显示我想要看到的内容?

解决方法

我们只需要在类中声明一个成员变量,并用它来储存字符串的内容:

1
2
3
4
5
6
7
8
9
private string txt1;
void Start() {
txt1 = "";
}
void OnGUI() {
txt1 = GUILayout.TextField(txt1, GUILayout.Width(100));
}

在上述代码中,我们声明了一个私有的字符串 txt1,并且用它来存储字符串。注意,TextField() 的返回值就是用户在文本框中输入的字符串。

这样,我们就解决了擦除重绘的问题。

GUILayout布局

GUILayout 默认垂直布局,如果想要改成水平布局,可以这么做:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void OnGUI() {
// 水平布局开始
GUILayout.BeginHorizontal();
// 文本框
txt1 = GUILayout.TextField(txt1, GUILayout.Width(100));
// 按钮,当鼠标从按钮上抬起时,才会返回true
if (GUILayout.Button("Button")) {
Debug.Log(1);
}
// 水平布局结束
GUILayout.EndHorizontal();
}

代码中用到了 BeginHorizontal() 和 EndHorizontal()。显然,所有在这两个方法之间的控件都将以水平方式排布。另外,你可以任意嵌套水平布局与垂直布局,达到自己想要的效果。

GUILayout 布局会自动调整控件的尺寸,如果你想要自定义控件的长度,那么 Button 等控件也支持可变参数数组。例如:

1
GUILayout.Button("Test", GUILayout.Width(500), GUILayout.Height(30))

GUILayou.Width(30)会返回一个设置空间宽度的 GUILayoutOption 对象,Height、MinWidth、MinHeight 同理,可以随自己的需要调用。

另外,如果是觉得控件之间太挤,可以使用GUILayout.Space()来调整间隙。

总结

最后再次强调一遍,OnGUI 是每帧都会进行擦除重绘的。如果想要的内容没有显示出来,可以自己创建一个变量,从而保证文本框中显示的值与返回的值使用同一个变量。