從零開始做一個SLG遊戲(六):UI系統擴充套件

遊資網發表於2019-10-18
現在UI系統已經有了最為基本的開啟和關閉的功能了,接下來需要對UI系統進行一個小小的擴充套件。

繼續以確認框作為例子:確認框這種形式在不同的地方都會使用到。比如上一篇文章中提到的科技樹功能,每點一個科技,都會有一個對應的確認框。

我們不可能也沒有必要針對每一個科技都製作一個新的確認框,所以除了開啟一個新的UI之外,我們還需要一些擴充套件性的功能。而確認框,將是一個非常典型的例子。

確認框的功能,其實包含兩層含義:

1.上一個UI會傳遞一些資訊給下一個UI,然後在下一個UI中,這些資訊會顯示出來。(比如科技樹確認框中“你確定要提升XXX科技嗎?”,或者關閉遊戲時“你確定要退出遊戲嗎?”這一類的話)

2.上一個UI會將自身的某些方法傳遞給下一個UI,這樣下一個UI就會執行這些方法。(比如提升科技的確認框,點了確認會提升對應的科技,退出遊戲的確認框,點了確定會退出遊戲)

所以,說白了就是要傳遞一些資訊給下一個UI,所以我們需要定義一個新的類,用來儲存這些資訊:


  1. public class UIEvent

  2. {

  3.         public UIType Type { get; private set; }

  4.         public Action Action { get; private set; }

  5.         public Hashtable Msg { get; private set; }

  6.         public UIEvent(UIType type)

  7.         {

  8.                 Type = type;

  9.                 Action = null;

  10.                 Msg = null;

  11.         }

  12.         public UIEvent(UIType type, Hashtable msg)

  13.         {

  14.                 Type = type;

  15.                 Action = null;

  16.                 Msg = msg;

  17.         }

  18.         public UIEvent(UIType type, Action act)

  19.         {

  20.                 Type = type;

  21.                 Action = act;

  22.                 Msg = null;

  23.         }



  24.         public UIEvent(UIType type, Action act, Hashtable msg)

  25.         {

  26.                 Type = type;

  27.                 Action = act;

  28.                 Msg = msg;

  29.         }



  30. }
複製程式碼

內容很簡單,UIType就不多說了,Action是一個委託,用於將上一個UI的函式傳遞過來,Msg是一個Hashtable,用於儲存一些資訊。

接下來去修改UIRoot類和BaseUI類:


  1. public class BaseUI : MonoBehaviour

  2. {

  3. ……

  4.         public void OpenUI(UIEvent uiEvent)//給OpenUI加入引數

  5.         {

  6.                 gameObject.SetActive(true);

  7.         }



  8. }





  9. public class UIRoot : MonoBehaviour {

  10. ……

  11.         public void OpenNormalUI(UIEvent uiEvent)

  12.         {

  13.                 UIType uiType = uiEvent.Type;

  14. ……

  15.                 CurrentUI.OpenUI(uiEvent);

  16.         }



  17.         public void OpenKeepAboveUI(UIEvent uiEvent)

  18.         {

  19.                 UIType uiType = uiEvent.Type;

  20.                 ……

  21.                 theUI.OpenUI(uiEvent);

  22.         }

  23. }
複製程式碼

之後更新所有用過這幾個函式的地方:

首先是開啟StartUI的地方

  1. public class UIRoot : MonoBehaviour {

  2. ……

  3.         private void Start()

  4.         {

  5.                 OpenNormalUI(new UIEvent(UIType.StartUI));

  6.         }

  7. ……

  8. }

  9. 然後是StartUI



  10. public class StartUI : BaseUI {

  11. ……

  12.         private void StartGame()

  13.         {

  14.                 UIRoot.Instance.OpenNormalUI(new UIEvent(UIType.GameSettingUI));

  15.         }

  16. }
複製程式碼

而後是GameSettingUI

  1. public class GameSettingUI : BaseUI {

  2. ……

  3.         public void StartGame()

  4.         {

  5.                 UIRoot.Instance.OpenNormalUI(new UIEvent(UIType.StartUI));

  6.         }



  7.         public void OpenTestUI()

  8.         {

  9.                 UIRoot.Instance.OpenKeepAboveUI(new UIEvent(UIType.TestAboveUI));

  10.         }

  11. }
複製程式碼

接下來是做一個確認框,確認框的UI主要包含3個部分:資訊描述,確認按鈕,取消按鈕

從零開始做一個SLG遊戲(六):UI系統擴充套件

從零開始做一個SLG遊戲(六):UI系統擴充套件

如圖,和以前流程一樣,做好了CheckBoxUI組建並放到了相應的位置。

資訊描述的組建是Content,確認按鈕是OKButton,取消是CancleButton。給CheckBoxUI掛上如下指令碼用以初始化。

  1. public class CheckBoxUI : BaseUI

  2. {

  3.         private Text Text;

  4.         private Button OKButton;

  5.         private Button CancelButton;

  6.         private void Awake()

  7.         {

  8.                 Text = UITool.FindChildByName(gameObject, "Content").GetComponent<Text>();



  9.                 OKButton = UITool.FindChildByName(gameObject, "OKButton").GetComponent<Button>();

  10.                 OKButton.onClick.AddListener(OnClickOk);



  11.                 CancelButton = UITool.FindChildByName(gameObject, "CancelButton").GetComponent<Button>();

  12.                 CancelButton.onClick.AddListener(OnClickCancel);

  13.         }





  14.         private void OnClickOk()

  15.         {

  16.         }



  17.         private void OnClickCancel()

  18.         {



  19.         }

  20. }
複製程式碼

在UIConfig中新增對應的配置:

  1. public class UIConfig

  2. {

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

  4.         {

  5. ……

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

  7.         };



  8. }



  9. public enum UIType

  10. {

  11. ……

  12.         CheckBoxUI,

  13. }
複製程式碼

然後再在TestAboveUI中加入對應的開啟入口:

  1. public class TestAboveUI : BaseUI

  2. {

  3. ……

  4.         private Button NewUIButton;

  5.         private void Awake()

  6.         {

  7. ……

  8.                 NewUIButton = UITool.FindChildByName(gameObject, "NewUIButton").GetComponent<Button>();

  9.                 NewUIButton.onClick.AddListener(OpenNewUI);

  10.         }

  11. ……

  12.         public void OpenNewUI()

  13.         {



  14.         }

  15. }
複製程式碼

其中OpenNewUI就是用來開啟新的UI的:

如果在該函式內加一句

UIRoot.Instance.OpenKeepAboveUI(new UIEvent(UIType.CheckBoxUI));
就可以開啟確認框了,但是要做的並不僅僅是開啟確認框,而是要讓確認框顯示對應的文字,並且點了確認後,要實現改視窗中包含的某個程式碼。

所以UIEvent內需要加更多的東西,作為測試,希望確認框執行的效果是在控制檯列印“1111111111”,並且在確認框中顯示“是否需要列印”。


  1.         public void OpenNewUI()

  2.         {

  3.                 UIEvent uiEvent = new UIEvent(

  4.                         UIType.CheckBoxUI,

  5.                         () => {

  6.                                 Debug.Log(111111111111);

  7.                         },

  8.                         new Hashtable

  9.                         {

  10.                                 { "content","是否需要列印"},

  11.                         }

  12.                         );

  13.                 UIRoot.Instance.OpenKeepAboveUI(uiEvent);

  14.         }
複製程式碼

這裡面的()=>{Debug.Log(111111111111);}是一個lamda表示式,等同於

  1.         public void OpenNewUI()

  2.         {

  3.                 UIEvent uiEvent = new UIEvent(

  4.                         UIType.CheckBoxUI,

  5.                         showLog,

  6.                         new Hashtable

  7.                         {

  8.                                 { "content","是否需要列印"},

  9.                         }

  10.                         );

  11.                 UIRoot.Instance.OpenKeepAboveUI(uiEvent);

  12.         }

  13.         void showLog()

  14.         {

  15.                 Debug.Log(111111111111);

  16.         }
複製程式碼

而後是在CheckBoxUI裡面實現,首先,我們需要用到多型的特性,所以要修改一下BaseUI的程式碼:

  1. public class BaseUI : MonoBehaviour

  2. {

  3. ……

  4.         public virtual void OpenUI(UIEvent uiEvent)

  5.         {

  6.                 gameObject.SetActive(true);

  7.         }

  8. ……

  9. }
複製程式碼

將OpenUI函式變為虛擬函式。然後將CheckBoxUI修改一下:

  1. public class CheckBoxUI : BaseUI

  2. {

  3. ……

  4.         private Action Action;



  5. ……



  6.         public override void OpenUI(UIEvent uiEvent)

  7.         {

  8.                 Text.text = uiEvent.Msg["content"].ToString();

  9.                 if (uiEvent.Action != null)

  10.                 {

  11.                         Action = uiEvent.Action;

  12.                 }

  13.                 base.OpenUI(uiEvent);

  14.         }



  15.         private void OnClickOk()

  16.         {

  17.                 Action();

  18.                 Action = null;

  19.                 UIRoot.Instance.CloseKeepAboveUI();

  20.         }



  21.         private void OnClickCancel()

  22.         {

  23.                 Action = null;

  24.                 UIRoot.Instance.CloseKeepAboveUI();

  25.         }

  26. }
複製程式碼

執行一下:

從零開始做一個SLG遊戲(六):UI系統擴充套件

從零開始做一個SLG遊戲(六):UI系統擴充套件

能夠成功的列印,並且顯示正確的資訊了。

自此,一個最為簡單的UI系統已經實現,接下來將實現的是遊戲基本的邏輯框架。

相關閱讀:

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

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

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

相關文章