从零开始做一个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个部分:信息描述,确认按钮,取消按钮



如图,和以前流程一样,做好了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. }
复制代码

运行一下:



能够成功的打印,并且显示正确的信息了。

自此,一个最为简单的UI系统已经实现,接下来将实现的是游戏基本的逻辑框架。

相关阅读:

从零开始做一个SLG游戏(一):六边形网格
从零开始做一个SLG游戏(二):用mesh实现简单的地形
从零开始做一个SLG游戏(三):用unity绘制图形

从零开始做一个SLG游戏(四):UI系统之主界面搭建
从零开始做一个SLG游戏(五):UI系统之弹窗功能

作者:观复
专栏地址:https://zhuanlan.zhihu.com/p/60049715

最新评论
暂无评论
参与评论

商务合作 查看更多

编辑推荐 查看更多