Unity 游戏框架:UI 管理神器 UI Kit (4)

UIPanelStack 也就是堆栈,一般只是用来完成返回上一页这个功能的。在没用堆栈管理页面信息之前,都是打开一个页面,然后在打开的页面上记录上一页面的信息,然后当页面点击返回时,再根据记录的上一个页面的信息打开上一个页面。这种实现在页面数量不多、跳转逻辑不复杂的情况下可以勉强应付。但是跳转逻辑比较复杂的情况下还是要实现一个,所以就添加了 UIPanelStack 这个功能。

起初的实现是所有的页面,每当关闭时页面信息全部压到 Stack 里。这里的页面信息定义如下:

public class UIPanelInfo { public IUIData UIData; public UILevel Level; public string AssetBundleName; public string PanelName; }

简单介绍下:

UIData 是 在关闭时页面的数据快照

Level 则是关闭时所在的层级

AssetBundleName 则是所加载的 AB 名,如果没有传入则为空。

PanelName 则是打开页面时传入的页面名字。

后来发现笔者参与的项目不需要每个页面都压入栈中,只是少数的几个页面需要。

所以提供了两个手动的 API。

UIMgr.Push<T>/UIMgr.Push(string panelName); UIMgr.Back(IUIPanel panel)/UIMgr.Back(string panelName);

Push 很容易理解,就是 UIPanel 的压栈操作。Back 则是,返回到最近 Push 进栈中的页面。

实现原理也很简单。

Push 时将传入的 panelName 对应的 Panel 关闭掉,生成 UIPanelInfo 后,将 UIPanelInfo 压入到栈中。

Back 则是将传入的 panelName 对应的 Panel 关闭掉,从 栈中弹出一个 UIPanelInfo,之后根据信息打开页面并传入 Info 中的数据。

核心代码:

UIManager.cs

public void Push(IUIPanel view) { if (view != null) { mUIStack.Push(view.PanelInfo); view.Close(); mAllUI.Remove(view.Transform.name); } } public void Back(string currentPanelName) { var previousPanelInfo = mUIStack.Pop(); CloseUI(currentPanelName); OpenUI(previousPanelInfo.PanelName, previousPanelInfo.Level, previousPanelInfo.UIData, previousPanelInfo.AssetBundleName); }

关于 UIPanelStack 介绍到这里。

这个功能目前还比较简陋,在 QFramework 文档中还没有进行介绍。不过相比把所有的页面信息都进行压栈操作,按需手动的这种方式更合适一些。

小结 (一)

事实上,独立测试的界面完全替代了 QFramework 初期所提供的 QApp 模块化的方式。这个不理解没关系,每个界面的开发已经是模块化了,不过只是从业务进行横向的模块化。已经够用了,毕竟大部分的项目都是进行 UI 界面的制作和修改。其他一些战斗系统等等,比较大的模块,也多少会依赖于 UI 部分,那么这种的推荐用一个 UI 界面进行一个模块的入口。总之在业务逻辑以及界面角度来看,已经支持了模块化的架构。

UI Kit 最佳实践 (二) 暂停界面与通信

接下来我们接着进行 UI Kit 最佳实践,之前我们完成了 UILevelPanel 和 UIGamePanel。

而 UIGamePanel 中的暂停功能还没有完成。点击暂停功能则应该打开暂停界面。

所以我们先完成暂停界面的制作:

UIGamePausePanel.prefab:

enter image description here

Image: 是对话框的白色背景

BtnContinue: 是继续按钮

BtnReplay: 是重玩按钮

BtnMain: 是主页按钮

其代码如下:

/* 2018.7 凉鞋的MacBook Pro (2) */ namespace QFramework.Example { public class UIGamePausePanelData : UIPanelData { // TODO: Query Mgr's Data } public partial class UIGamePausePanel : UIPanel { protected override void InitUI(IUIData uiData = null) { mData = uiData as UIGamePausePanelData ?? new UIGamePausePanelData(); //please add init code here } protected override void ProcessMsg (int eventId,QMsg msg) { throw new System.NotImplementedException (); } protected override void RegisterUIEvent() { BtnMain.onClick.AddListener(() => { CloseSelf(); UIMgr.ClosePanel<UIGamePanel>(); UIMgr.OpenPanel<UIMainPanel>(); }); BtnReplay.onClick.AddListener(() => { Log.E("BtnPlay Clicked"); }); BtnContinue.onClick.AddListener(() => { CloseSelf(); }); } } }

代码比较简单,主要是三个按钮的事件注册。

而 UIGamePanel.cs 进行暂停按钮的注册:

/* 2018.7 凉鞋的MacBook Pro (2) */ namespace QFramework.Example { public class UIGamePanelData : UIPanelData { public int LevelIndex = 1; } public partial class UIGamePanel : UIPanel { protected override void InitUI(IUIData uiData = null) { mData = uiData as UIGamePanelData ?? new UIGamePanelData(); //please add init code here Level.text = "第" + mData.LevelIndex + "关"; } protected override void ProcessMsg (int eventId,QMsg msg) { } protected override void RegisterUIEvent() { BtnPause.onClick.AddListener(() => { UIMgr.OpenPanel<UIGamePausePanel>(UILevel.PopUI); }); } } }

原来的 BtnPause 点击之后进行一些日志的输出,现在则改为了打开 UIGamePausePanel 页面。

这里层级为 UILevel.PopUI。

这样一个打开暂停页面的功能就完成了。

结果如下:

enter image description here

但是一般的暂停页面没有这么简单。

当打开暂停页面的时候,正在进行的游戏应该全部暂停。这里最容易的实现就是 Time.timeScale = 0.0f;

不过这不是重点,当继续游戏时候,还要通知 UIGamePanel 或者对应的 GameManager 进行暂停的恢复。

这就涉及到了对象之间通信的问题。

最简单的方式就是,在 UIGamePausePanel 中获取 UIGamePanel ,然后进行相应恢复操作。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wsppfj.html