3D Game Programming & Design:UI系統--Quest Log 公告牌
UI系統概述
UI 即 User Interface(用戶界面)的簡稱。在許多軟件中,採用狹義的概念,特指窗體、面板、按鈕、文本框等人們熟悉的人機交互元素,及其組織與風格(也稱皮膚)。Unity UI 系統採用上述狹義概念。
5.0 及以後 - Unity GUI / UGUI 是面向對象的 UI 系統。所有 UI 元素都是遊戲對象,友好的圖形化設計界面, 可在場景渲染階段渲染這些 UI 元素。
-
UGUI 的產生與優勢
隨着遊戲開發的普及,爲了讓設計師也能參與參與程序開發,從簡單的地圖編輯器、菜單編輯器等工具應運而生。設計師甚至不需要程序員幫助,使用這些工具就可直接創造遊戲元素,乃至產生遊戲程序。除此之外,現代遊戲 UI 必須要滿足以下要求:
- 跨設備執行,自動適應不同分辨率
- UI 元素與遊戲場景融爲一體的交互
- 支持複雜的佈局
- 多攝像機支持
以至於即使優秀的程序員在現代 UI 面前,傳統代碼驅動的 UI 面臨開發效率低下,難以調試等問題。 對於 Unity 平臺, 當 NGUI: Next-Gen UI kit 的出現使得不依賴 Unity Pro 功能,使用所見即所得(WYSIWYG)設計工具,集成了 tweening 運動管理系統, 可以製作多數 2D 遊戲,直接威脅了 Unity 的生意。 Unity 最終高薪聘了 NGUI 的主設計師,最終又分道揚鑣,於是就有了 UGUI,青出於藍而勝於藍!
UGUI 的優勢:
- 所見即所得(WYSIWYG)設計工具
- 支持多模式、多攝像機渲染
- 面向對象的編程
UGUI 基礎
畫布(Cavas)
畫布(Cavas)是繪圖區域, 同時是 ui 元素的容器。 容器中 ui 元素及其子 UI 元素都將繪製在其上。 擁有Canvas組件的遊戲對象都有一個畫布,它空間中的子對象,如果是 UI 元素將渲染在畫布上。畫布區域在場景視圖中顯示爲矩形。這使得定位UI元素變得非常容易,無需隨時顯示遊戲運行視圖。
UI 佈局基礎
每個UI元素都被表示爲一個矩形,爲了相對於 Canvas 和 其他 UI 元素實現定位,Unity 在 Transform 基礎上定義了 RectTransform (矩形變換) 支持矩形元素在 2/3D 場景中變換。
UI 組件與元素
UI 部件都是用 Script 開發的自定義組件。包括在 UI、Layout 和 Rendering 等分類中。
1、可視化組件
可視化組件,在組件 UI 分類中,包括:
- Text:顯示的文本的文本區域。可以設置字體,字體樣式,字體大小以及文本是否具有豐富的文本功能。
- Image:顯示圖片的區域。可以設置GUI精靈、色彩。
- Raw Image:原始圖像採用紋理,進行 UV 矩形貼圖。
- Mask:Mask不是一個可見的UI控件。遮罩將子元素限制(即“掩蔽”)爲父元素的形狀。如果孩子比父控件大,那麼只有適合父節點遮罩的部分是可見的。
Effects:應用各種簡單的效果,例如簡單的投影或輪廓。
2、UI 交互元素
UI 交互元素是 GameObject,它擁有 UI 交互組件、UI可視化組件、及相關組件的組合,以及一些 UI 子元素構成,以方便用戶在設計場景中創建交互界面。
例如:Button 元素,除了 UI 必須擁有的 RectTransform 和 Canvas renderer 外,還有 Image 和 Button 組件,以及一個 Text 子元素。
- Button
- Toggle
- Toggle Group
- Slider
- Scrollbar
- Dropdown
- Input Field
- Scroll Rect (Scroll View)
其他更多關於UI系統的基礎操作知識,請移步Unity3d的官方文檔。
編程實踐
作業要求
UI 效果製作(你僅需要實現以下效果之一)
進入 NGUI 官方網站,使用 UGUI 實現以下效果
- Inventory 揹包系統
- Quest Log 公告牌
- Scroll View 選擇板
以上例子需要使用 Unity web player, 僅支持以下操作系統與瀏覽器,參見官方下載
Windows 版 IE11
Mac OS X 10.7 Safari
出現界面需要等待較長時間,打開頁面讓它慢慢加載
我選擇的題目是實現Quest Log 公告牌。
基本配置
按官方手冊,EventSystem 在一個場景中 有且僅能有一個,它將遊戲操縱桿、鍵盤、鼠標、觸摸屏、觸摸屏與 UI 對象交互事件,如 Click,MouseMOver,DragEnter 等等,傳遞給遊戲對象對應的行爲組件。
菜單通常由一個 Canvas 和 若干 Panel 組成的,所有 UI 元素組成一個樹形結構。
在canvas下新建一個滾動視圖scoll view。然後在Scroll View -> Viewport -> Content下添加垂直列表組件vertical layout group和Button1,2,3以及對應的Text1,2,3用於顯示公告的按鈕和文字。
在button和text上分別設置要顯示的文字內容,文字格式等等。
之後可以直接通過UGUI對公告牌的大小位置以及其他屬性進行設置。調整垂直列表中的間距還有自適應寬高等的屬性。
最後我們可以對公告牌和整個canvas分別添加背景圖片,這裏我就是在網上找的圖片素材,然後添加到asset的img文件夾下即可,唯一要注意的是,要將這些背景圖片的Texture Type變爲Sprite(2D and UI),才能夠添加成功。
代碼分析
這一次的作業因爲很多部分都是用UGUI直接可以操作的,所以代碼比較簡單,主要就是實現公告文字的隱藏和展開。
這裏我們使用了C#的協程接口IEnumerator,它允許你爲自己的集合類型編寫枚舉器,IEnumerator迭代器和yield關鍵字需要配合使用。Unity協程長的類似於線程,但卻不是線程。因爲協程仍然是在主線程中執行,且在使用時不用考慮同步與鎖的問題。協程只是控制代碼等到特定的時機後再執行後續步驟。我們可以寫一段順序的代碼,標明哪裏需要暫停,然後在下一幀或者一段時間後,系統會繼續執行這段代碼。通過每幀來改變文本的角度和文本的高度,來實現隱藏和展開的效果。
完整代碼如下:
public class Board : MonoBehaviour {
// 分別對應按鈕和文本內容
private Button button;
public Text text;
private float height; // 公告文本的高度
private int frame = 20; // 公告內容變化幀數
void Start()
{
// 獲取button,添加監聽事件
button = this.gameObject.GetComponent<Button>();
button.onClick.AddListener(showOrHide);
// 並獲取公告文本的高度,以便還原
height = text.rectTransform.sizeDelta.y;
}
void showOrHide()
{
// 判斷文本是選擇隱藏還是顯示
if (text.gameObject.activeSelf)
StartCoroutine(hide());
else
StartCoroutine(show());
}
IEnumerator hide()
{
float h = height;
for (int i = 0; i < frame; i++)
{
h -= height / frame;
text.rectTransform.sizeDelta = new Vector2(text.rectTransform.sizeDelta.x, h);
// 在這停頓,下一幀再執行
yield return null;
}
text.gameObject.SetActive(false);
// 禁用文本
}
IEnumerator show()
{
float h = 0;
text.gameObject.SetActive(true);
// 激活文本
for (int i = 0; i < frame; i++)
{
h += height / frame;
text.rectTransform.sizeDelta = new Vector2(text.rectTransform.sizeDelta.x, h);
// 在這停頓,下一幀再執行
yield return null;
}
}
}
完成代碼後,我們需要把它掛載到我們的每一個button之上,並把每個button對應的text拖到相應的欄目裏面即可。
遊戲界面效果
隱藏文本:
展開文本: