分类:Unity、C#、VS2015
创建日期:2016-04-27
一、简介
Unity 5.x内置了—套完整的GUI系统,提供了从布局、控件到皮肤的—整套GUI解决方案,因此可直接利用它做出各种风格和样式的GUI界面,并且扩展性很强(程序员可以基于已有的控件创建出适合自己需求的控件)。
有两种使用GUI的办法,一种是直接将UI添加到层次视图或者场景视图中,然后通过GUI脚本去控制它;另一种是直接通过GUI脚本去创建。
二、直接添加UI控件到场景中
下图是Unity 5.3.4内置的UI控件,这些UI控件的用法和其他游戏对象(GameObject)的用法相似,可直接将其添加到场景或层次视图中,并通过检视器修改其参数:
例如,向场景中添加一个Text,并通过检视器修改它的字体大小为24,颜色为红色:
下面是在层次视图中看到的结果:
也许下面的另一个场景截图更能让你明白它的用法:
除了可将UI直接添加到场景中并在OnGUI()函数中通过脚本去控制它以外,还可以在OnGUI()函数中通过脚本去控制。
再次提醒注意:
(1)GUI代码需要在 OnGUI() 函数中控制,不能放在 Update() 函数中。
(2)GUI中的坐标位置与Input.mousePosiotion的鼠标位置不同。在Unity GUI中,屏幕坐标系以“左上角”为原点(0,0),“右下角”为(screen.Wdth,screen.Height)。其中screen.Width为屏幕宽度,screen.Height为屏幕高度,以像素为单位。而对于Input.mousePosition来说,它的屏幕“左下角”为原点(0,0),屏幕“右上角”为(Screen.Width,Screen.Height)。
三、OnGUI()函数
UnityGUI 控件使用一种称为 OnGUI() 的特殊函数。只要启用了包含的脚本,每帧都会自动调用OnGUI() 函数。
GUI 控件本身结构很简单。例如,下面是“等级加载器”的示例代码:
using UnityEngine; using System.Collections; public class GUITest : MonoBehaviour { void OnGUI () { // 制作背景盒 GUI.Box(new Rect(10,10,100,90), "Loader Menu"); // 制作第一个按钮。按下这个按钮将执行 Application.Loadlevel (1) if(GUI.Button(new Rect(20,40,80,20), "Level 1")) { Application.LoadLevel(1); } // 制作第二个按钮。 if(GUI.Button(new Rect(20,70,80,20), "Level 2")) { Application.LoadLevel(2); } } }
此示例是一个完整的功能性等级加载器。如果你将此脚本拖到游戏对象 (GameObject) 上,则进入播放模式 (Play Mode) 时就会看到下面的菜单:
由于 OnGUI() 代码在每一帧都会被调用,因此你不需要明确创建或销毁 GUI 控件。如果你需要在特定的时间显示控件,可使用任何一种脚本逻辑来操作,例如:
void OnGUI () { if (Time.time % 2 < 1) { if (GUI.Button (new Rect (10,10,200,20), "Meet the flashing button")) { print ("You clicked me!"); } }
此处,GUI.Button() 每隔一秒调用一次,因此此按钮会出现然后消失。因此,如果按这样的方式来实现,只有在按钮可见时用户才能单击它。
声明 GUI 控件时必需有三条关键信息:
控件类型(显示的位置,显示的内容)
其中:
控件类型:是通过调用 UnityGUI 类或 GUILayout 类中的一个函数来声明的。
位置:这是 GUI 控件函数中的第一个参数。示例代码中的Rect() 定义了四种属性:最左端位置、最顶端位置、控件总宽度和控件总高度。所有这些值都是整数(与像素值对应)。
所有 UnityGUI 控件都在屏幕空间 (Screen Space)中运行,左上角为(0,0),右下角为最大坐标值(Screen.width,Screen.height)。
再看一个例子:Rect(10, 20, 300, 100) 定义矩形 (Rectangle),该矩形始于坐标:10,20,结束于坐标(310,120),即:(10+300,20+100)。
使用Screen.width 和 Screen.height 属性可获取屏幕空间的总尺寸。例如:
void OnGUI() { GUI.Box (new Rect (0,0,100,50), "Top-left"); GUI.Box (new Rect (Screen.width - 100,0,100,50), "Top-right"); GUI.Box (new Rect (0,Screen.height - 50,100,50), "Bottom-left"); GUI.Box (new Rect (Screen.width - 100,Screen.height - 50,100,50), "Bottom-right"); }
这段C#代码的效果是:四个按钮分别显示在屏幕的四个角。
用于 GUI 控件的第二个参数是用控件显示的实际内容,它既可以是文本,也可以是图像。如果希望显示图像,先声明一个二维纹理 (Texture2D)类型的公共变量,并将变量名称作为内容参数即可:
public Texture2D controlTexture; void OnGUI () { GUI.Label (new Rect (0,0,100,50), controlTexture); }
下面是更接近真实世界场景的代码示例:
using UnityEngine; using System.Collections; public class GUITest : MonoBehaviour { public Texture2D icon; void OnGUI () { if (GUI.Button (new Rect (10,10, 100, 50), icon)) { print ("you clicked the icon"); } if (GUI.Button (new Rect (10,70, 100, 20), "This is text")) { print ("you clicked the text button"); } } }
下面的C#代码演示了如何同时显示图像和文本:
public Texture2D icon; void OnGUI () { GUI.Box (new Rect (10,10,100,50), new GUIContent("This is text", icon)); }
下面的C#代码演示了如何同时显示文本和工具提示(Tooltip)。当鼠标在控件上方悬停时,Tooltip就会显示在适当的位置:
void OnGUI () { // 该行向 GUI 工具提示输入“This is the tooltip” GUI.Button (new Rect (10,10,100,20), new GUIContent ("Click me", "This is the tooltip")); // 该行读取并显示 GUI 工具提示的内容 GUI.Label (new Rect (10,40,100,20), GUI.tooltip); }
下面的C#代码演示了如何同时显示图像、文本和工具提示(Tooltip):
public Texture2D icon; void OnGUI () { GUI.Button (new Rect (10,10,100,20), new GUIContent ("Click me", icon, "This is the tooltip")); GUI.Label (new Rect (10,40,100,20), GUI.tooltip); }
当鼠标在控件上方悬停时,Tooltip的内容“This is the tooltip”就会显示出来。
四、通过脚本创建UI控件
这里仅介绍如何通过脚本去创建和使用UI控件。
1、Label
Label控件适合用来显示文本信息或者图片,它不会响应鼠标或键盘消息。
void OnGUI ()
{
GUI.Label (new Rect (25, 25, 100, 30), "这是Label");
}
2、Box
该控件可用来绘制带有边框背景的立方体或长方体文字或图片。
GUI.Box(new Rect(0,0,Screen.width*0.5,Screen.height*0.5),"Hello");
3、Button、RepeatButton
该控件用来绘制晌应单击事件的按钮。
当有按钮单击事件发生时,Button函数返回true,否则返回false。因此,按钮的事件处理脚本需要写在控件代码if语句条件为true的代码区域中。
using UnityEngine; using System.Collections; public class GUITest : MonoBehaviour { public Texture2D btnTexture; void OnGUI() { if(GUI.Button(new Rect(10,10,50,50),btnTexture)) { Debug.Log("你单击了图片按钮"); } if (GUI.Button(new Rect(10, 10, 50, 50), "请点击我!")) { Debug.Log("你单击了文字按钮"); } } }
Button控件在每次单击事件中只响应一次,如果想处理鼠标左键长按的事件,可以使用RepeatButton控件。
RepeatButton会在左键按下期间一直返回true。
4、TextField、PasswordField、TextArea
TextField:单行文本框
TextArea:多行文本框
PasswordField:密码输入框
游戏中经常需要用到信息输入的窗口,比如聊天窗、用户信息的输入等,这些情况可以使用TextField控件:
private string textFieldString = "text field"; void OnGUI() { textFieldString = GUI.TextField(new Rect(25, 25, 100, 30), textFieldString); }
TextArea控件与TextField的用法类似,区别就是TextField是单行的,TextArea可以编辑多行文字:
private string textAreaString = "text area"; void OnGUI() { textAreaString = GUI.TextArea(new Rect(25, 25, 100, 30), textAreaString); }
PasswordField控件用于绘制密码输入框,经常用于用户登录界面中:
public string pwd="12345"; void OnGUI() { pwd = GUI.PasswordField(new Rect(10, 10, 200, 20), pwd, '*'); }
5、Toggle
Toogle:复选框。相当于CheckBox。
Toogle控件一般用作开关,每次单击Toogle都会在“开”和“关”之间切换。例如:
private bool toggleBool = true; void OnGUI() { toggleBool = GUI.Toggle(new Rect(25, 25, 100, 30), toggleBool, "Toggle"); if(toggleBool == true){//……} }
也可以显示一个图片开关,其用法和Label类似。
6、ToolBar、SelectionGrid
ToolBar:单选按钮工具栏。相当于在工具栏中显示一组RadioButton。
SelectionGrid:多排工具栏 (Toolbar)。它可以自动决定栅格中显示的列数和行数。仍然是一次仅可激活一个“按钮”(Button)。
ToolBar控件适用于绘制一组按钮,在这些按钮中同时只激活—个,可以利用它来制作选项卡式的工具栏:
private int toolbarInt = 0; private string[] toolbarStrings = { "Toolbar1", "Toolbar2", "Toolbar3" }; void OnGUI() { toolbarInt = GUI.Toolbar(new Rect(25, 25, 250, 30), toolbarInt, toolbarStrings); }
SelectionGrid通过一个整数可跟踪“栅格选择”(SelectionGrid) 中激活的“按钮”(Button)。必须提供该整数作为此函数的参数和返回值。提供的内容数组中的元素数目将决定“栅格选择”(SelectionGrid) 中显示的“按钮” (Button) 的数目:
private int selectionGridInt = 0; private string[] selectionStrings = { "Grid 1", "Grid 2", "Grid 3", "Grid 4" }; void OnGUI() { selectionGridInt = GUI.SelectionGrid(new Rect(25, 25, 300, 60), selectionGridInt, selectionStrings, 2); }
7、HorizontalSlider、VertialSlider
滑动条(Slider)一般用于音量调整、进度显示、数值调整的GUI界面中。
“滑动条”(Slider) 的当前位置以浮点数形式存储。要显示滑动条的当前位置,需要提供 该浮点数作为函数的参数。另有两个值用于确定最小值和最大值。如果希望滑动条钮是可调的,则将滑动条值浮点数指定为“滑动条"(Slider) 函数的返回值。
在Unity中,Slider控件分为水平和垂直2种布局方式,对应的函数为HorizontalSlider和VertialSlider。
下面是HorizontalSlider的基本用法:
private float hSliderValue = 0.0f; void OnGUI() { hSliderValue = GUI.HorizontalSlider(new Rect(25, 25, 100, 30), hSliderValue, 0.0f, 10.0f); }
下面是VertialSlider的基本用法:
private float vSliderValue = 0.0f; void OnGUI() { vSliderValue = GUI.VerticalSlider(new Rect(25, 25, 100, 30), vSliderValue, 10.0f, 0.0f); }
8、HorizontalScrollbar、VertialScrollbar
滚动条(ScrollBar)常用于页面区域的滚动,例如文档浏览。在Unity中,ScrollBar控件分为水平和垂直2种,对应的GUI函数为HorizontalScrollbar和VertialScrollbar。
水平滚动条(HorizontalScrollbar) 的执行与水平滑动条(Horizontal Slider) 相同,但有一个例外之处:另有一个参数控制“滚动条”(Scrollbar) 钮自身的宽度。
private float hScrollbarValue; void OnGUI() { hScrollbarValue = GUI.HorizontalScrollbar(new Rect(25, 25, 100, 30), hScrollbarValue, 1.0f, 0.0f, 10.0f); }
垂直滚动条的用法与其类似,这里就不再举例了。
9、ScrollView
ScrollView用来在GUI界面中绘制一个滚动视图区域,并旦可以通过滚动条来控制要显示的区域内容。
ScrollView通过成对调用BeginScrollView和EndScrollView来完成绘制。在这2个函数之间的GUI代码会绘制在滚动视图内部区域中。
private Vector2 scrollViewVector = Vector2.zero; private string innerText = "I am inside the ScrollView"; void OnGUI() { // 开始“滚动视图”(ScrollView) scrollViewVector = GUI.BeginScrollView(new Rect(25, 25, 100, 100), scrollViewVector, new Rect(0, 0, 400, 400)); // 向“滚动视图”(ScrollView) 输入内容 innerText = GUI.TextArea(new Rect(0, 0, 400, 400), innerText); // 结束“滚动视图”(ScrollView) GUI.EndScrollView(); }
10、Window
可以将Window看作是控件的容器,即把其他控件都绘制在这个窗口中,这样可以方便地调整窗口内所有控件的位置,以及显示隐藏。
Window函数会调用另外一个函数来进行绘制控件的工作。在绘制控件函数中,控件的位置为窗口自身坐标系下的位置,如果控件位置超出了窗口的区域,将不会显示。
如果想让窗口可拖动,在绘制函数中调用DragWindow函数可以设置窗口的拖动位置。
private Rect windowRect = new Rect(20, 20, 220, 100); void OnGUI() { windowRect = GUI.Window(0, windowRect, WindowFunction, "My Window"); } void WindowFunction(int windowID) { // 在此处绘制窗口内的所有控件 GUI.Button(new Rect(60,50,100,20),"OK"); …… GUI.DrawWindow(new Rect(0,0,120,20)); //让窗口可以通过标题栏拖动位置 }
三、GUI.changed
要检测用户是否对 GUI 进行过操作(如点击“按钮”(Button)、拖动滑动条等等),可通过脚本读取 GUI.changed 的值。如果用户进行过操作则该值为 true,通过它可以很容易确定用户的输入。
对于“工具栏”(Toolbar) 可能会出现这种情况,即你想根据“工具栏”(Toolbar) 中点击“按钮”(Button) 时都分配该值,而不是仅在点击其中一个“按钮”(Button) 时进行分配,此时可以用下面的代码实现:
using UnityEngine; using System.Collections; public class GUITest : MonoBehaviour { private int selectedToolbar = 0; private string[] toolbarStrings = {"One", "Two"}; void OnGUI () { // 确定到此帧时哪个按钮处于激活状态以及其是否被点击过 selectedToolbar = GUI.Toolbar (new Rect (50, 10, Screen.width - 100, 30), selectedToolbar, toolbarStrings); // 如果用户在此帧点击了一个按钮,则处理其输入 if (GUI.changed) { Debug.Log("The toolbar was clicked"); if (0 == selectedToolbar) { Debug.Log("First button was clicked"); } else { Debug.Log("Second button was clicked"); } } } }