分類: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"); } } } }