NLDClient-yudde/ProjectNLD/Assets/Code/Scripts/Framework/UI/UIWindow.Lifecycle.cs

597 lines
40 KiB
C#
Raw Normal View History

2025-09-22 17:45:42 +08:00
using Cysharp.Threading.Tasks;
using DG.Tweening;
using Framework;
using PhxhSDK;
using UnityEngine.UI;
public abstract partial class UIWindow
{
2025-09-10 16:05:21 +08:00
/*
UIWindow (Lifecycle)
1. Load -
UIManager.CreateWindow()
2025-09-10 16:05:21 +08:00
GameObject
UIWindow
2. Init -
2025-09-13 14:12:31 +08:00
UIWindow.Init(data) // 窗口初始化(公共接口,不可重写) ║
2025-09-10 16:05:21 +08:00
DoInit() // 基础初始化 ║
2025-09-13 14:12:31 +08:00
*AutoBindField() // 绑定UI组件引用 ║
2025-09-10 16:05:21 +08:00
InitScreenAdaption() // 屏幕适配 ║
_TryBindBgClose() // 绑定背景关闭按钮 ║
2025-09-10 16:05:21 +08:00
*OnInit() // 初始化UI状态设置默认值 ║
3. Show -
2025-09-13 14:12:31 +08:00
UIWindow.ShowWindow(data) // 显示窗口(公共接口,不可重写) ║
*OnBeforeShow(data) // 显示前检查 ║
DoShow() // 基础显示逻辑 ║
2025-09-11 16:51:41 +08:00
SetActive(true) // 激活GameObject ║
*OnAfterShow(data) // 显示后处理 ║
2025-09-11 16:51:41 +08:00
UI // EventManager.Send ║
2025-09-10 16:05:21 +08:00
4. Update -
2025-09-13 14:12:31 +08:00
UIWindow.Update(dt) // 更新入口(公共接口,不可重写) ║
*OnUpdate(dt) // 每帧更新处理UI逻辑 ║
2025-09-10 16:05:21 +08:00
5. Refresh -
2025-09-13 14:12:31 +08:00
UIWindow.Refresh(data) // 数据刷新(公共接口,不可重写) ║
*OnRefresh(data) // 刷新UI内容更新显示数据 ║
2025-09-10 16:05:21 +08:00
6. Hide -
2025-09-13 14:12:31 +08:00
UIWindow.HideWindow() // 隐藏窗口(公共接口,不可重写) ║
*OnHide() // 隐藏回调 ║
2025-09-10 16:05:21 +08:00
SetActive(false) // 隐藏GameObject ║
UI // EventManager.Send ║
2025-09-10 16:05:21 +08:00
7. Close -
2025-09-13 14:12:31 +08:00
UIWindow.CloseWindow() // 关闭窗口(公共接口,不可重写) ║
DestroyWindow() // 内部销毁逻辑 ║
*OnHide() // 隐藏回调 ║
*OnRelease() // 释放资源,清理引用 ║
DoRelease() // 基础资源释放 ║
Destroy(gameObject) // 销毁GameObject ║
// AssetManager.Unload ║
🔒 :
🎯 : InitShowShowRefresh
:
🛡 :
📋 : 使
使
: UIManager.CreateWindow() Init(data) ShowWindow(data)
: Refresh(data)
: HideWindow() / ShowWindow()
: CloseWindow()
- *
🔸 *OnBeforeInit(data) -
DoInitOnInit
使OnInit
OnInit()
🔸 *OnInit() - UI
DoInit
UI
GameObject访UI
🔸 *AutoBindField() -
DoInit
UI
🔸 *OnBeforeShow(data) -
DoShowOnShow
false
使
2025-09-24 20:46:04 +08:00
🔸 *OnShow(data) -
2025-09-13 14:12:31 +08:00
SetActive
Refresh
2025-09-11 16:51:41 +08:00
🔸 *OnAfterShow(data) -
2025-09-13 14:12:31 +08:00
SetActive
🔸 *OnUpdate(dt) -
使
🔸 *OnRefresh(data) -
Refresh(data)
Show
Refresh(data)
🔸 *OnHide() -
2025-09-10 16:05:21 +08:00
🔸 *OnRelease() -
2025-09-13 14:12:31 +08:00
OnHide
Tween
🚫
Init, ShowWindow, Refresh, HideWindow
OnXxx
OnXxxbase.OnXxx()
OnInit使OnBeforeInit
ShowRefresh
OnRelease
使OnUpdate
Refresh(data)ShowWindow(data)
💡
"模板方法模式"
2025-09-10 16:05:21 +08:00
*/
2025-09-12 15:18:50 +08:00
#region Lifecycle Management
2025-09-10 21:02:34 +08:00
/// <summary>
/// 初始化窗口
/// </summary>
2025-09-12 15:18:50 +08:00
/// <param name="data">初始化数据</param>
2025-09-10 16:05:21 +08:00
public void Init(object data = null)
{
try
{
OnBeforeInit(data);
if (isInited)
{
DebugUtil.LogWarning("window : {0} already inited", WindowName);
}
else
{
DoInit();
OnInit();
isInited = true;
}
2025-09-10 16:05:21 +08:00
}
catch (System.Exception e)
2025-09-10 16:05:21 +08:00
{
DebugUtil.LogError("window : {0} init window error: {1}", WindowName, e.Message);
}
2025-09-10 16:05:21 +08:00
}
2025-09-12 15:18:50 +08:00
/// <summary>
/// 显示窗口
/// </summary>
/// <param name="data">显示数据</param>
public void ShowWindow(object data = null)
{
try
{
if (_isShow)
{
DebugUtil.LogWarning("window : {0} is show, can't show again", WindowName);
}
2025-09-12 15:18:50 +08:00
if (!OnBeforeShow(data))
{
DebugUtil.LogError("window : {0} on before show return false", WindowName);
return;
}
DoShow();
OnShow(data);
if (gameObject is null)
2025-09-12 15:18:50 +08:00
{
DebugUtil.Log("UI已被销毁:{0}", WindowName);
}
else
{
gameObject.SetActive(true);
}
_isShow = true;
2025-09-22 17:45:42 +08:00
bool isShowOpenAnim = IsShowOpenAnim;
if (isShowOpenAnim)
{
AnimShow(() =>
{
OnAfterShow(data);
EventManager.Instance.Send(EventManager.EventName.UIOpen, WindowName);
}).Forget();
}
else
{
OnAfterShow(data);
EventManager.Instance.Send(EventManager.EventName.UIOpen, WindowName);
}
2025-09-12 15:18:50 +08:00
}
catch (System.Exception e)
{
DebugUtil.LogError("window : {0} show window error: {1}", WindowName, e.Message);
}
}
2025-09-10 21:02:34 +08:00
/// <summary>
2025-09-12 15:18:50 +08:00
/// 更新入口
2025-09-10 21:02:34 +08:00
/// </summary>
2025-09-12 15:18:50 +08:00
public void Update(float dt)
2025-09-10 16:05:21 +08:00
{
try
{
_notchScreenAdapter?.UpdateCheck();
OnUpdate(dt);
}
catch (System.Exception e)
{
DebugUtil.LogError("window : {0} update window error: {1}", WindowName, e.Message);
}
}
2025-09-12 15:18:50 +08:00
2025-09-10 21:02:34 +08:00
/// <summary>
2025-09-12 15:18:50 +08:00
/// 刷新窗口数据
2025-09-10 21:02:34 +08:00
/// </summary>
2025-09-12 15:18:50 +08:00
/// <param name="data">新数据</param>
public void Refresh(object data)
2025-09-10 21:02:34 +08:00
{
try
2025-09-10 21:02:34 +08:00
{
if (isInited)
{
OnRefresh(data);
}
else
{
DebugUtil.LogError("window : {0} not inited", WindowName);
}
2025-09-10 21:02:34 +08:00
}
catch (System.Exception e)
2025-09-10 21:02:34 +08:00
{
DebugUtil.LogError("window : {0} refresh with data error: {1}", WindowName, e.Message);
2025-09-10 21:02:34 +08:00
}
}
2025-09-12 15:18:50 +08:00
/// <summary>
/// 隐藏窗口
/// </summary>
public void HideWindow()
{
if (!_isShow)
{
DebugUtil.LogWarning("window : {0} is hide, can't hide again", WindowName);
}
try
{
if (UIManager.Instance.WindowInfos.TryGetValue(WindowName, out var windowInfo))
{
if (windowInfo.UIOpenType == UIOpenType.FullScreen)
{
if (!CameraManager.Instance.CheckMainCameraIsActive())
{
CameraManager.Instance.SetMainCameraActive(true);
}
}
}
OnHide();
gameObject?.SetActive(false);
_isShow = false;
EventManager.Instance.Send(EventManager.EventName.UIHide, WindowName);
}
catch (System.Exception e)
{
DebugUtil.LogError("window : {0} hide window error: {1}", WindowName, e.Message);
}
}
/// <summary>
/// 关闭窗口
/// </summary>
/// <param name="closeType">关闭类型</param>
public async void CloseWindow(UIWindowCloseType closeType)
{
try
{
IsClosing = true;
DebugUtil.LogG($"关闭UI:{WindowName}, closeType{closeType}");
if (UIManager.Instance.CheckWindowIsFullScreen(this))
{
if (_shutMainCamera)
{
CameraManager.Instance.SetMainCameraActive(true);
}
}
if (closeType == UIWindowCloseType.HideAndDestroy)
{
var last = UIManager.Instance.GetLast();
if (last == this)
2025-09-12 15:18:50 +08:00
{
DebugUtil.LogG($"PopWindow{this.WindowName}");
UIManager.Instance.PopWindow();
}
if (UIManager.Instance.UiWindowStack.Count > 0)
{
if (UIManager.Instance.CheckWindowIsFullScreen(this))
2025-09-12 15:54:45 +08:00
{
var window = UIManager.Instance.GetLastFullScreen();
if (window != null && window != this)
{
if (UIManager.Instance.CheckIsWindowInStack(this))
{
UIManager.Instance.ForceRemoveWindow(this);
DebugUtil.LogG($"UI出栈,{WindowName}");
}
}
for (int i = UIManager.Instance.UiWindowStack.Count - 1; i >= 0; i--)
2025-09-12 15:54:45 +08:00
{
var latestWindow = UIManager.Instance.UiWindowStack[i];
latestWindow.ShowWindow();
if (UIManager.Instance.CheckWindowIsFullScreen(latestWindow))
break;
2025-09-12 15:54:45 +08:00
}
}
else
2025-09-12 15:18:50 +08:00
{
UIManager.Instance.ForceRemoveWindow(this);
2025-09-12 15:18:50 +08:00
}
}
bool isShowCloseAnim = IsShowOpenAnim;
if (isShowCloseAnim)
2025-09-12 15:18:50 +08:00
{
UIManager.Instance.BlockUIForCloseOperation();
await AnimHide(() =>
{
DestroyWindow();
UIManager.Instance.RemoveWindow(mWindowName);
IsClosing = false;
});
2025-09-12 15:18:50 +08:00
}
else
{
UIManager.Instance.RemoveWindow(mWindowName);
DestroyWindow();
IsClosing = false;
}
}
else if (closeType == UIWindowCloseType.ForceDestroy)
{
// 强制清除所有界面时使用
DestroyWindow();
UIManager.Instance.RemoveWindow(mWindowName);
IsClosing = false;
}
}
catch (System.Exception e)
{
DebugUtil.LogError("window : {0} close window error: {1}", WindowName, e.Message);
}
}
2025-09-10 21:02:34 +08:00
#endregion
2025-09-12 15:18:50 +08:00
#region Internal Implementation
/// <summary>
/// 执行基础初始化
/// </summary>
private void DoInit()
{
_isShow = false;
_shutMainCamera = UIManager.Instance.IsShutMainCamera(WindowName);
IsShowOpenAnim = UIManager.Instance.GetIsAutoPlayAnim(WindowName);
AutoBindField();
InitScreenAdaption();
_TryBindBgClose();
}
2025-09-10 21:02:34 +08:00
/// <summary>
2025-09-12 15:18:50 +08:00
/// 执行显示逻辑
/// </summary>
2025-09-10 19:54:45 +08:00
private void DoShow()
{
if (UIManager.Instance.WindowInfos.TryGetValue(WindowName, out var windowInfo))
{
if (CameraManager.Instance.CheckMainCameraIsActive())
{
if (windowInfo.UIOpenType == UIOpenType.FullScreen)
{
2025-09-12 15:18:50 +08:00
// 特殊处理主界面
if (_shutMainCamera && WindowName != UINameConst.UI_MainPanel)
{
CameraManager.Instance.SetMainCameraActive(false);
}
}
}
}
}
/// <summary>
/// 销毁窗口
/// </summary>
private void DestroyWindow()
{
DebugUtil.LogG($"DestroyWindow:{WindowName}");
2025-09-12 15:18:50 +08:00
OnHide();
gameObject?.SetActive(false);
_isShow = false;
EventManager.Instance.Send(EventManager.EventName.UIHide, WindowName);
if (gameObject)
{
2025-09-09 20:26:41 +08:00
if (isInited)
{
OnRelease();
2025-09-12 15:18:50 +08:00
DoRelease();
2025-09-09 20:26:41 +08:00
isInited = false;
}
2025-09-12 15:18:50 +08:00
if (UIManager.Instance.UIWindowObjDic.ContainsKey(gameObject))
{
UIManager.Instance.UIWindowObjDic.Remove(gameObject);
}
UnityEngine.Object.Destroy(gameObject);
}
AssetManager.Instance.Unload(string.Format(UIManager.UI_PREFAB_PATH, mWindowName), true);
gameObject = null;
}
2025-09-10 19:54:45 +08:00
/// <summary>
2025-09-12 15:18:50 +08:00
/// 基础资源释放
/// </summary>
2025-09-12 15:18:50 +08:00
private void DoRelease()
{
2025-09-12 15:18:50 +08:00
EventManager.Instance.Send(EventManager.EventName.UIDestroy, WindowName);
2025-09-12 10:54:10 +08:00
2025-09-12 15:18:50 +08:00
UnLoad();
_openAnimSeq?.Kill();
_assetReferenceManager?.Dispose();
_assetReferenceManager = null;
_notchScreenAdapter = null;
_graphicRaycasterManager = null;
}
/// <summary>
/// 绑定背景关闭按钮
/// </summary>
private void _TryBindBgClose()
{
var trans = transform.Find("BgClose");
if (trans)
{
var btn = trans.GetComponent<Button>();
if (btn)
{
BindButton(btn, () =>
{
var clickAudio = btn.GetComponent<ClickAudio>();
if (clickAudio)
{
if (clickAudio.IsPlayAudio && !string.IsNullOrEmpty(clickAudio.AudioKey))
{
AudioManager.Instance.PlayAudio(clickAudio.AudioKey);
}
else
{
CommonUtilsFramework.PlayUICommonSound();
}
}
if (_onBgCloseFunc == null)
{
CloseWindow(UIWindowCloseType.HideAndDestroy);
return;
}
_onBgCloseFunc?.Invoke();
});
}
}
}
#endregion
2025-09-12 15:18:50 +08:00
#region Virtual Methods
2025-09-12 15:18:50 +08:00
// Init Phase
/// <summary>
/// 初始化前预处理不推荐使用建议在OnInit中处理
/// </summary>
2025-09-24 20:46:04 +08:00
[System.Obsolete("OnBeforeInit已废弃请使用OnInit方法替代。OnInit提供更清晰的初始化流程和更好的代码组织。")]
protected virtual void OnBeforeInit(object data = null){}
/// <summary>
2025-09-12 15:18:50 +08:00
/// UI初始化
/// </summary>
protected virtual void OnInit(){}
2025-09-12 15:18:50 +08:00
/// <summary>
/// 自动绑定字段
/// </summary>
protected virtual void AutoBindField(){}
2025-09-11 16:51:41 +08:00
2025-09-12 15:18:50 +08:00
// Show Phase
/// <summary>
/// 显示前检查
/// </summary>
2025-09-12 10:54:10 +08:00
protected virtual bool OnBeforeShow(object data)
{
return true;
}
2025-09-11 16:39:35 +08:00
/// <summary>
2025-09-12 15:18:50 +08:00
/// 显示时处理
2025-09-11 16:39:35 +08:00
/// </summary>
2025-09-24 20:46:04 +08:00
[System.Obsolete("OnShow已废弃请使用OnAfterShow方法替代。OnAfterShow在窗口完全显示后调用提供更稳定的显示时机。")]
protected virtual void OnShow(object data){}
/// <summary>
2025-09-12 15:18:50 +08:00
/// 显示后处理
/// </summary>
protected virtual void OnAfterShow(object data){}
2025-09-12 15:18:50 +08:00
/// <summary>
2025-09-12 15:18:50 +08:00
/// 每帧更新
/// </summary>
protected virtual void OnUpdate(float dt){}
2025-09-12 15:18:50 +08:00
// Refresh Phase
/// <summary>
2025-09-12 15:18:50 +08:00
/// 数据刷新
/// </summary>
protected virtual void OnRefresh(object data) {}
2025-09-12 15:18:50 +08:00
// Hide Phase
/// <summary>
2025-09-12 15:18:50 +08:00
/// 隐藏时处理
/// </summary>
protected virtual void OnHide(){}
2025-09-12 15:18:50 +08:00
// Release Phase
/// <summary>
2025-09-12 15:18:50 +08:00
/// 资源释放
/// </summary>
protected virtual void OnRelease(){}
2025-09-12 15:18:50 +08:00
#endregion
}