TERPGDemo/Books/3-5-UI模块.md
2025-04-22 17:16:40 +08:00

127 lines
4.6 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 3-5.UI模块 - UIModule
一个游戏70%都是UI剩下30%才是GamePlay所以有一套简洁强大的商业化UI模块以及UI开发工作流将是项目的一大利器能够提高至少一倍的开发效率。(配合事件模块实现MVE[Model - View - Event]事件驱动架构)
UI脚本为纯C#实现脱离Mono的生命周期由UIModule的帧更新驱动并管理UI的生命周期。
IUIBehaviour为UI通用行为接口、UIBase为UI基类、UIWindow为UI窗口基类UIWidget为UI组件基类。
## 前期配置:
注意m_item节点为特殊节点表示是UI下的UIWidget组件不会继续往下遍历生成UI代码。若需要这个UIWidget组件m_item的代码则在m_item右键生成这个组件的UI脚本。
Scene窗口下右键ScriptGenerator菜单下About目录有默认UI命名前缀规范。
![image](src/3-5-1.png)
有自定义需求可以在TEngineSetting下进行自定义。
![image](src/3-5-2.png)
### 开发工作流:
1.遵守前期默认配置或者自定义配置进行UI编排
![image](src/3-5-3.png)
2.在UI的根节点右键ScriptGenerator生成UI代码到剪贴板上注-使用-UniTask的生成代码可以做异步事件流驱动的UI。
![image](src/3-5-4.png)
3.自行创建UI脚本到需要的目录下并复制UI脚本。
## 举例示范
``` csharp
// 同步打开面板
GameModule.UI.ShowUI<GameMainUI>([nullable]userData);
// 异步打开面板
GameModule.UI.ShowUIAsync<GameMainUI>([nullable]userData);
namespace GameLogic
{
/// <summary>
/// BattleMainUI面板
/// <remarks>UIWindow需要以下特性UILayer可以自行定义fullScreen表示为全屏面板会停止和隐藏这个面板堆栈后面的面板。</remarks>
/// </summary>
[Window(UILayer.Bottom,fullScreen:true)]
class BattleMainUI : UIWindow
{
private TouchMove m_touchView;
#region 脚本工具生成的代码
private RectTransform m_rectContainer;
private GameObject m_itemTouch;
private Button m_btnLeaveBattle;
private GameObject m_goTopInfo;
private Button m_btnPause;
public override void ScriptGenerator()
{
m_rectContainer = FindChildComponent<RectTransform>("m_rectContainer");
m_itemTouch = FindChild("m_rectContainer/m_itemTouch").gameObject;
m_btnLeaveBattle = FindChildComponent<Button>("m_btnLeaveBattle");
m_goTopInfo = FindChild("m_goTopInfo").gameObject;
m_btnPause = FindChildComponent<Button>("m_goTopInfo/m_btnPause");
m_btnLeaveBattle.onClick.AddListener(OnClickLeaveBattleBtn);
m_btnPause.onClick.AddListener(OnClickPauseBtn);
}
#endregion
#region 事件
private void OnClickPauseBtn()
{
BattleSys.Instance.Pause = !BattleSys.Instance.Pause;
}
private void OnClickLeaveBattleBtn()
{
BattleSys.Instance.StopBattle(isBattleEnd:false,isWin:false);
}
#endregion
//注册事件举例
public override void RegisterEvent()
{
//通过AddUIEvent这样注册事件会把事件的生命周期绑定给面板面板销毁的时候自动移除监听。
AddUIEvent(ActorLogicEventDefined.OnMainPlayerBagDataChange, RefreshUI);
}
public override void BindMemberProperty()
{
//特殊的m_item节点的域不属于父级UIWindows所以如注意所说需要同样创建这个UIWidget的脚本并生成代码过去。 可以如下创建或者走type、path创建。
m_touchView = CreateWidget<TouchMove>(m_itemTouch);
}
......
}
}
namespace GameLogic
{
/// <summary>
/// 移动操作UIWidget。
/// </summary>
class TouchMove : UIWidget, IUICtrlMove
{
public override void BindMemberProperty()
{
}
//注意Update只有在重写了此方法才会驱动这个Widget或者面板的Update。
public override void OnUpdate()
{
TProfiler.BeginSample("CheckMoveTouchFinger");
CheckMoveTouchFinger();
TProfiler.EndSample();
TProfiler.BeginSample("UpdateTouchMovePos");
UpdateTouchMovePos();
TProfiler.EndSample();
TProfiler.BeginSample("UpdateKeyMove");
UpdateKeyMove();
TProfiler.EndSample();
}
......
}
}
```
## UI进阶
UI面板需要标记UIWindowAttribute以标识层级(可以自行定义)和是否全屏。全屏面板则会把下层面板的Visible设置为false。
![image](src/3-5-5.png)