從零開始做一個SLG遊戲(五):UI系統之彈窗功能

遊資網發表於2019-10-14
從零開始做一個SLG遊戲(五):UI系統之彈窗功能
圖源/網路

接下來實現彈窗功能。

首先,需要明確的是,這邊所說的彈窗到底是什麼?

此處所說的彈窗,指的是非主介面的所有彈出視窗,裡面包括一些介面,比如系統設定、科技介面等。

這些視窗開啟的時候,主介面依然是存在的,並且可能作為UI的背景之一,因為這些UI會比主介面要小一些。

並且,很可能同一時間會開啟多個彈窗,比如最典型的的,我在科技樹彈窗上,選擇提升某個科技,這時候會彈出一個確認的新彈窗,並且前面那個科技樹彈窗還存在。

為了便於操作,可以定這樣的規則:

彈窗上操作可以彈出新的彈窗,但是玩家只能操作最新出現的那個彈窗。

繼續回到科技樹那個例子上,我在科技樹上選擇了科技A,這時彈出了一個視窗,讓我確認是否花費xxx升級科技A。

這時候,有些遊戲是可以不點那個確認視窗,繼續點科技樹上的科技B的。點完後,那個確認彈窗的文字會變成“是否花費xxx升級科技B”。

而我簡化了一下這個操作並規定,這時候玩家只能操作那個確認彈窗介面,要麼點取消,要麼點確認。玩家想要改升級科技B,需要先點取消把彈窗關閉,然後再選擇科技B。

當然,如果以後覺得可以優化體驗,可以改成前面說的這種,多個視窗並存的模式,但不是現在。這麼一來,邏輯就簡單多了,方面快速把遊戲原型給做出來。

接下來是具體功能的實現,首先是修改遊戲的引數名:

  1. public class UIRoot: MonoBehaviour {

  2. ……

  3.         private readonly Dictionary<UIType, BaseUI> uiDic = new Dictionary<UIType, BaseUI>();

  4.         private readonly Stack<BaseUI> CurrentAboveUI = new Stack<BaseUI>();

  5. ……

  6. }
複製程式碼

將原來的NormalUIDic重新命名為UIDic。因為接下來,彈窗的UI也將存放到這個字典中。

同時新建一個Stack用於存放正在使用的UI,類似於上一篇文章中的CurrentUI。

Stack型別即堆疊,有點類似於List,用於存放多個相同型別的物件。和List不同的是,他的儲存是先進先出的,即我按A-B-C的順序依次存入一個Stack之後,我要取出,必然只能是C-B-A。這一特點和彈窗的設計是一致的。

Stack的用法很簡單,這裡主要用到了下面幾個方法:

  1. Stack<a> aStack = new Stack<a>();//建立一個a型別的堆疊

  2. int count = aStack.Count;//獲取堆疊中元素的個數

  3. a newA = new a();

  4. aStack.Push(newA);//將一個元素存放進堆疊

  5. a theA = aStack.Pop();//獲得堆疊中最新存進去的元素,並在堆疊中刪除它
複製程式碼

於是,我們可以模仿上一篇文章中如何開啟一個新介面的方法寫如何開啟一個彈窗:

  1. private readonly Stack<BaseUI> CurrentAboveUI = new Stack<BaseUI>();       

  2. public void OpenKeepAboveUI(UIType uiType)

  3. {

  4.         BaseUI theUI;

  5.         if (UIDic.ContainsKey(uiType))

  6.         {

  7.                 theUI = UIDic[uiType];

  8.         }

  9.         else

  10.         {

  11.                 theUI = Instantiate(Resources.Load<BaseUI>(UIConfig.UIPath[uiType])) as BaseUI;

  12.                 UITool.AddChild(theUI.transform, KeepAboveUI);

  13.                 UIDic.Add(uiType, theUI);

  14.         }

  15.         CurrentAboveUI.Push(theUI);//將theUI放入堆疊

  16.         theUI.transform.SetAsLastSibling();//將該介面放在最上面那一層

  17.         theUI.OpenUI();

  18. }
複製程式碼

和主介面不同的是,由於主介面是互斥的,所以主介面沒有單獨必要寫一個關閉主介面的函式。但彈窗需要:

  1. public void CloseKeepAboveUI()

  2.         {

  3.                 if (CurrentAboveUI.Count == 0)

  4.                 {

  5.                         return;

  6.                 }

  7.                 BaseUI theUI = CurrentAboveUI.Pop();//獲得最上一層的UI,並在堆疊中刪除它

  8.                 theUI.CloseUI();

  9.         }
複製程式碼

       
這個方法用來刪除最上層的彈窗,畢竟在設計中,彈窗只能操作最上面的那個。

好了,現在可以做幾個介面來測試一下:

先右鍵UIRoot下Keep Above UI這個gameobject,然後選擇建立一個新的Panel,並重新命名為Test Above UI

然後再在這個Panel上,放2個image和2個button,組成一個最簡單的UI。這個UI包括背景(用於填充整個視窗以防止點選到主介面上的按鈕上去),視窗本體,關閉按鈕,開啟新彈窗的按鈕。

從零開始做一個SLG遊戲(五):UI系統之彈窗功能

從零開始做一個SLG遊戲(五):UI系統之彈窗功能

其中NewUIButton是中間藍色的那個,用於開啟另一個新的彈窗(這個彈窗還沒做),黃色按鈕為關閉按鈕即CloseButton。

從零開始做一個SLG遊戲(五):UI系統之彈窗功能

建立一個新的指令碼,叫TestAboveUI,並讓它繼承自BaseUI,並加入以下程式碼,以實現關閉視窗的功能:

  1. public class TestAboveUI : BaseUI

  2. {        private Button CloseButton;

  3.         private void Awake()

  4.         {

  5.                 CloseButton = UITool.FindChildByName(gameObject, "CloseButton").GetComponent<Button>();

  6.                 CloseButton.onClick.AddListener(CloseThisUI);

  7.         }





  8.         public void CloseThisUI()

  9.         {

  10.                 UIRoot.Instance.CloseKeepAboveUI();

  11.         }

  12. }
複製程式碼

從零開始做一個SLG遊戲(五):UI系統之彈窗功能

掛在剛剛我們建的那個視窗上。

從零開始做一個SLG遊戲(五):UI系統之彈窗功能

將該視窗做成prefab放在其他的視窗prefab一起。

在UIConfig檔案中新增對應的索引:

  1. public class UIConfig

  2. {

  3.         public static Dictionary<UIType, string> UIPath = new Dictionary<UIType, string>

  4.         {

  5.                 { UIType.StartUI,"UIPrefabs/StartUI"},

  6.                 { UIType.GameSettingUI,"UIPrefabs/GameSettingUI"},

  7.                 { UIType.TestAboveUI,"UIPrefabs/TestAboveUI"},

  8.         };



  9. }
複製程式碼

我們再開啟上一篇文章中做的GameSettingUI,並新增一個新的Button,名叫OpenTestUI。

從零開始做一個SLG遊戲(五):UI系統之彈窗功能

從零開始做一個SLG遊戲(五):UI系統之彈窗功能

開啟GameSettingUI的指令碼,新增該按鈕相關的程式碼:

  1. public class GameSettingUI : BaseUI {

  2.         ……

  3.         private Button openTestUI;

  4.         private void Awake()

  5.         {

  6.                 ……



  7.                 openTestUI = UITool.FindChildByName(gameObject, "OpenTestUI").GetComponent<Button>();

  8.                 openTestUI.onClick.AddListener(OpenTestUI);



  9.         }



  10. ……



  11.         public void OpenTestUI()

  12.         {

  13.                 UIRoot.Instance.OpenKeepAboveUI(UIType.TestAboveUI);

  14.         }

  15. }
複製程式碼

原理上一篇文章中已經講過了,就不展開說了。

執行程式,可以在GameSettingUI視窗中,開啟彈窗,然後點選黃色按鈕關閉。

從零開始做一個SLG遊戲(五):UI系統之彈窗功能

相關閱讀:


從零開始做一個SLG遊戲(一):六邊形網格
從零開始做一個SLG遊戲(二):用mesh實現簡單的地形
從零開始做一個SLG遊戲(三):用unity繪製圖形



從零開始做一個SLG遊戲(四):UI系統之主介面搭建

作者:觀復
專欄地址:https://zhuanlan.zhihu.com/p/60004604

相關文章