用Unity做半個2D戰棋小遊戲(五):新增常用的介面

遊資網發表於2019-03-15
寫在最前

這次想要一個簡單且傳統的戰棋小遊戲,大概的玩法是:在2D世界裡建立一張由六邊形地塊組成的戰鬥地圖,敵我雙方依據體力在地圖上輪流行動並向對方發動攻擊,先消滅掉所有敵人的一方將獲得勝利。

預計將分為以下幾篇:

1、建立戰場

根據預定尺寸生成戰場地圖,並隨機一些障礙物。

2、新增戰場地圖功能

實現戰場格子點選反饋,地圖導航及範圍選定。

3、新增對戰雙方

向戰場中新增作戰單位,作戰單位按照一定規則輪流行動,可進行移動、攻擊等。

4、加入玩家控制

新增可以隨時顯示戰況的Hud、為作戰單位新增血條等。

5、新增常用的介面

建立介面管理器,加入一些常用的介面。

6、新增常用的戰場顯示

為戰鬥單位新增血條,加入傷害文字顯示。

7、擴充套件作戰單位

豐富作戰單位的型別,新增職業,並加入若干不同型別的技能。

8、擴充套件戰場地圖

豐富戰場地圖,加入地形及道具等元素。

9、規範戰鬥配置

可以通過規範化的資料結構配置戰場、職業、技能、道具等。

本次的主題是:新增常用的介面。

專案程式碼會上傳至我的Github:https://github.com/elsong823/HalfSLG中,有興趣的同學請自取。

|目標

使用Unity自帶的UGUI替換之前的GUI來實現一些常用介面:

1、包含開始戰鬥按鈕及戰鬥結束時提示文字的主介面。

2、玩家手動操作時,輔助選擇移動、攻擊及待命的彈出皮膚。

3、點選地圖、戰鬥單位時,彈出的詳情展示皮膚。

實現後的效果如下圖:

用Unity做半個2D戰棋小遊戲(五):新增常用的介面
戰鬥結束時顯示的友情提醒

用Unity做半個2D戰棋小遊戲(五):新增常用的介面
行動選擇選單

用Unity做半個2D戰棋小遊戲(五):新增常用的介面
戰場單位資訊皮膚

不難看出,當UGUI碰撞上專業的素材後,一個個絕美的介面瞬間躍然屏上。這也給了那些常說“程式設計師不懂美”的傢伙們一記響亮的耳光。

|關於如何製作介面

這些介面都是用UGUI製作的,並沒有什麼難度,相信上手過UGUI或NGUI的同學,只要碰到精美的紋理貼圖,都能輕鬆完成。

用Unity做半個2D戰棋小遊戲(五):新增常用的介面
使用的是一套高雅灰主題的專業UI紋理素材

本文不會對UGUI的使用做詳細介紹,我們將重點聊聊對介面的管理。

因為只要找到了方法,做出漂亮的介面就只是時間問題罷了。

而至於證明“程式設計師也能憑自己的能力作出專業介面”這件事,相信上面已經做到了。

受專案大小及時間所限,這裡會使用一套輕量級的介面管理方式。而在此之前,讓我們先做一些前期準備工作。

|分配相機

為介面的繪製單獨分配一個相機(介面相機),並調整介面相機和戰場相機上的Clear Flags、CullingMask和Depth設定。

用Unity做半個2D戰棋小遊戲(五):新增常用的介面
介面相機與戰場相機的設定

整個介面系統的根畫布(ScreenCanvas),是一個型別為ScreenSpace-Camera的Canvas,它的父節點ScreenUIRoot上有專門渲染介面的介面相機。

|設定層級

ScreenCanvas下設5個節點,分別對應5個層級:背景層、基礎層、彈出層、頂層和Debug層.

用Unity做半個2D戰棋小遊戲(五):新增常用的介面
介面的層級結構

各層的功能為:

背景層:裝飾性的、非功能性的介面。

基礎層:常駐的介面(主介面、角色頭像、快捷操作欄等)。

彈出層:點選後彈出的介面(各功能介面)。

頂層:強制顯示在最上層的介面(Tips介面或走馬燈等)。

Debug層:開發時輔助除錯用。

這些層級從下到上放置,遮擋關係是上層遮擋下層。當然,其順序、層數和名稱可根據實際需求進行調整。

需要注意的是,這5個節點(Transform)並非是必須的,它們只是為了Debug時能更直觀的檢視層級間的關係,真正用於用於區分層級的是Canvas上的SortingLayer和OrderInLayer屬性。

用Unity做半個2D戰棋小遊戲(五):新增常用的介面
SortingLayers設定中的層級與對應的節點

用Unity做半個2D戰棋小遊戲(五):新增常用的介面
不同介面上Canvas所設定的Layer和Order值

|介面管理流程

比起程式碼,我覺得還是看圖來的更直觀些。

用Unity做半個2D戰棋小遊戲(五):新增常用的介面
介面管理流程

整個介面管理可以簡單拆解為四個部分:開啟介面、關閉介面、層級重新整理及介面重新整理,下面我們依次介紹。

|開啟介面

用Unity做半個2D戰棋小遊戲(五):新增常用的介面

開啟介面的邏輯很簡單,但需要注意的是,為了更好的使用記憶體,介面管理器維護了兩個介面快取區:常駐快取和臨時快取。開啟介面時如果需要載入新的介面,先去這兩個快取區中檢視一下是否有快取過的介面,從快取區載入比重新讀取新的介面效率要高。

|關閉介面

用Unity做半個2D戰棋小遊戲(五):新增常用的介面

當我們要關閉介面時,介面管理器會根據它的“儲存策略”決定其被關閉後的去留,有些會被放入到常駐快取區,有些會被放到臨時快取區,而有些則會被直接移除。

這就好比兩性交往中女生犯錯通常當時就會被原諒;男生犯錯通常需要好好表現一段時間才有可能被原諒;而單身狗連犯錯的機會都沒有。

|層級重新整理

用Unity做半個2D戰棋小遊戲(五):新增常用的介面

上面介紹了開啟和關閉介面。其實它們都可以被看成是在“顯示介面”。因為關閉介面也可以理解為“被這個介面遮擋覆蓋的介面,可能需要顯示了”。

因此,當有介面被開啟或關閉後,介面管理器會從上到下的讓各層重新整理自己的顯示狀態及對螢幕的遮擋狀態,並將這個遮擋狀態向下傳遞,用作後面層級的顯示判斷。

|介面重新整理

用Unity做半個2D戰棋小遊戲(五):新增常用的介面

我們知道介面的重新整理和顯示是有代價的,因為它們會對CPU及GPU的效能造成開銷。因此我為每個介面設定了是否遮擋了螢幕、不可見時是否仍然重新整理及Dirty屬性。

如果一個介面遮擋了螢幕,那麼它下面的介面首先應該被“隱藏”以減小渲染的壓力;其次如果不可見的介面沒有被設定為“不可見時仍然重新整理”,則當需要重新整理它時(介面資料發生了變化),也只是被打上Dirty標記,並在下次需要顯示的時候再重新整理。

|介面的生命週期函式

上面流程圖中的藍色部分,是介面的生命週期函式,它們會在適當的時間被介面管理器、層級或介面自身呼叫。

Init:初始化,介面首次被載入後呼叫。

OnPush:介面被顯示前,加入層級時被呼叫。

OnShow:介面被顯示時呼叫。

UpdateView:介面需要被重新整理時呼叫。

OnHide:介面被隱藏時呼叫。

OnPopup:介面被關閉,從層級中移除時呼叫。

OnExit:介面不需要被快取,被Destroy前呼叫。

用Unity做半個2D戰棋小遊戲(五):新增常用的介面
一次完整的介面開啟、重新整理、關閉過程

|介面的儲存策略

介面被關閉後會根據預設的儲存策略決定去留,這裡定義的儲存策略有以下三種。

自動移除:很少用到的介面,每次關閉時會被直接Destroy掉。

用Unity做半個2D戰棋小遊戲(五):新增常用的介面
自動移除策略

臨時快取區:較為常用的介面,在關閉時我們把它放入一個有深度設定的快取區,這個快取區當收入一個新的介面時,會判斷快取量是否已超過預設深度;如果超過了預設深度,會將最早快取的介面彈出並Destroy掉。

用Unity做半個2D戰棋小遊戲(五):新增常用的介面
臨時快取區策略(深度為2)

常駐快取區:需要頻繁開關的介面,在關閉時我們會把它們放入一個沒有深度設定(快取個數限制)的快取區。

用Unity做半個2D戰棋小遊戲(五):新增常用的介面
常駐快取區策略(僅唯一存在介面可被設定為常駐)

|介面配置

我使用ScriptableObject物件作為介面配置的載體。每次建立新的介面時,需要同樣建立一個配置物件,並將兩者進行關聯。介面自身及使用者可以通過讀取這個物件獲取介面的配置資訊。

用Unity做半個2D戰棋小遊戲(五):新增常用的介面
介面配置檔案的屬性構成

當然我們可以稍微修改Editor,新增一些輔助工具幫助我們快速生成介面配置檔案。

用Unity做半個2D戰棋小遊戲(五):新增常用的介面
一個簡單的配置檔案重新整理器

|寫在最後

至此,新增常用的介面篇就介紹到這裡,詳細程式碼可以移步Github:

https://github.com/elsong823/HalfSLG。

感謝您能讀到這裡。

願不忘初心。

下回見。

作者:/zt枸杞憂天
來源:騰訊遊戲學院
原地址:http://gad.qq.com/article/detail/289094

相關文章