框架整理學習
UIMgr:
一、數據結構與算法
1.1 關鍵數據結構1.2 算法邏輯
成員變量 類型 說明 m_Ctrls
List<PageInfo>
當前正在顯示的所有 UI 頁面 m_Caches
List<PageInfo>
已打開過、但現在不顯示的頁面(緩存池)
查找緩存頁面:從
m_Caches
中倒序查找是否已有對應ePageType
頁面,找到則重用。頁面加載:從資源管理器
ResMgr
加載 prefab 并綁定控制器/視圖組件。頁面關閉:從
m_Ctrls
移除,添加到m_Caches
,供后續復用。刷新頁面:關閉當前頁面再重新打開。
這些邏輯大多采用線性搜索(O(n)),足夠應對中小型游戲中的 UI 數量。
二、基本語法與結構說明
2.1 類繼承public class UIMgr : Singleton<UIMgr>
繼承自泛型單例
Singleton<T>
,保證UIMgr
全局唯一實例,可通過UIMgr.Inst
獲取。
2.2 組件掛載與初始化ResMgr.Inst.Get(name, null, Constant.m_UiPath).AddComponent<PageInfo>();
加載 UI prefab 后添加
PageInfo
組件,并手動獲取并設置BaseCtrl
和BaseView
。
2.3 控制器與視圖綁定ctrl.m_PageInfo = showPage; view.m_PageInfo = showPage;
通過雙向引用讓頁面、控制器和視圖互相關聯。
? 三、實現思路詳解
3.1 UI 生命周期管理view.Init(); ctrl.Init(); ctrl.Show(); view.Show();
初始化(
Init
):綁定數據、設置 UI 元素初始狀態顯示(
Show
):打開 UI 頁面隱藏(
UnShow
):關閉 UI 頁面,但不銷毀對象3.2 緩存復用機制
UI 關閉時并不直接銷毀,而是放入m_Caches
中,節省加載資源開銷,提高性能。
3.3 事件廣播機制EventMgr.Inst.Broadcast(IntEvt.Fetch(EventId.OpenUI, ...));
3.4 靈活的關閉方式(函數重載)
支持通過:
頁面類型(
EPageType
)控制器(
BaseCtrl
)視圖(
BaseView
)頁面信息(
PageInfo
)等不同方式關閉頁面。
? 四、補充建議與未來優化方向
數據結構優化
問題 建議 線性查找效率較低 將 m_Ctrls
和m_Caches
改為Dictionary<EPageType, PageInfo>
,可快速查找頁面緩存永不銷毀,可能內存溢出 定期檢查 m_Caches
長度,進行清理(LRU 算法或設置上限)
解耦結構設計當前邏輯是“管理器 + 控制器 + 視圖”三層結構,推薦引入更標準的 UI 框架設計模式,例如:
MVC(Model-View-Controller)
MVVM(Model-View-ViewModel)
ECS(Entity Component System) —— 用于大型項目
異步加載支持
如果資源加載較慢,建議將:ResMgr.Inst.Get(...)
替換為異步方法,支持 loading 動畫和取消操作。
動態層級系統
目前層級(sortingOrder)是注釋掉的,建議恢復并基于m_Crrls.Count自動設置:showPage.GetComponent<UIPanel>().sortingOrder = m_Ctrls.Count;
確保 UI 正確疊加,避免層級錯亂。
? 五、總結:
優點 💡 不足點 ?? 簡潔明了、結構清晰 查找效率低、資源管理偏靜態 支持多種關閉方式 緩存機制缺乏清理策略 模塊化控制器與視圖 控制器與視圖綁定寫死在框架中
?? 一、什么是
Dictionary<EPageType, PageInfo>
?
Dictionary<K, V>
是 C# 中的一種泛型集合類,也叫 字典、哈希表,它存儲的是 “鍵-值對(Key-Value Pair)”:Dictionary<K, V>
K
是鍵(Key)類型,必須是唯一的。
V
是值(Value)類型,可以重復。
在你的場景中:Dictionary<EPageType, PageInfo>
EPageType
是一個枚舉類型(表示頁面類型,例如:主頁、背包、商店)
PageInfo
是頁面的信息類,包含了 Controller 和 View 以及一些元數據。
? 舉個例子:var dic = new Dictionary<EPageType,PageInfo>();dic[EPageType.Home] = homePageInfo; dic[EPageType.Shop] = shopPageInfo;//獲取 var page = dic[EPageType.Home];
相比于
List<PageInfo>
,使用Dictionary
的最大優勢是:查找速度是 O(1),非常快!
Dictionary空間換時間 和?List?時間換空間。
一、什么是“空間換時間” vs “時間換空間”?? 空間換時間
意思是:通過多占用內存空間,來提升運行效率(尤其是查找效率)。
例如:
創建一個大型的數組或哈希表,快速定位數據。
為了加快訪問速度,犧牲一些內存來保存冗余數據或索引。
? 時間換空間
意思是:通過減少內存占用,但犧牲一點運行效率(特別是遍歷或查找速度)。
例如:
僅保存最少必要信息,每次都從頭計算或查找。
不額外保存中間狀態,減少內存消耗。
二、對比Dictionary
和List
三、空間換時間的例子(Dictionary)
特性 Dictionary<K, V>
List<T>
本質結構 哈希表(Hash Table) 數組(Array) 查找效率 O(1) 常數時間(哈希定位) O(n) 線性時間(需要遍歷整個列表) 插入效率 快,但哈希沖突時略慢 尾部插入快,插入中間則可能慢 占用內存 高:維護哈希表結構、桶數組等 低:僅維護數據本身 是否保證順序 不保證插入順序 保證插入順序 使用場景 快速定位、查找、映射(如字典、緩存系統) 順序存儲、小集合、頻繁遍歷 Dictionary<EPageType, PageInfo> uiPages;
背后的原理是:
系統為每個
Key
計算哈希值(比如將EPageType.Shop
映射為 13573)。根據哈希值快速跳轉到該數據的內存地址。
這種方式會使用額外的內存結構(如哈希桶、數組、鏈表等)來保證快速訪問。這就是典型的用空間換時間:提高速度,但犧牲內存。
不需要遍歷,直接就能拿到結果。
四、時間換空間的例子(List)
List<PageInfo> uiPages;
你只能寫:
foreach (var page in uiPages) {if (page.Type == EPageType.Shop){return page;} }
此時:
查找每個元素需要 O(n) 時間。
不需要額外的哈希結構,節省內存。
數據越多,性能下降越明顯。
這是時間換空間:節省內存,但犧牲了執行效率。
五、現實生活類比
場景 類比解釋 Dictionary
圖書館:一本書有唯一編號(哈希值),你可以一秒鐘定位這本書的位置(快速查找)。為了這個,你得先建一套編號系統,占用一定資源(空間)。 List
堆書桌:書都堆一起了,你要找《C#教程》,只能一本本翻過去,慢,但不需要額外占地(空間節省)。
總結一句話:
類別 定義 Dictionary 是“空間換時間” 用更多的內存結構(如哈希表)來提升數據查找速度,適合頻繁查找、修改的數據集合 List 是“時間換空間” 內存占用少,但每次操作如查找需要從頭遍歷,適合數據量小、頻繁順序處理的場景
?
PageInfo
、BaseCtrl
、BaseView
是什么?作用是什么?1.
PageInfo
:頁面的容器(頁面元信息)
PageInfo
主要負責綁定以下三件事:
頁面類型
EPageType
控制器組件
BaseCtrl
視圖組件
BaseView
UI 面板
UIPanel
(來自 FairyGUI)
gameObject
對象本身它像是一個頁面的數據模型,保存了一切有關這個 UI 頁面的運行時數據。
2.BaseCtrl
:控制器(邏輯層)所有頁面控制器都應該繼承自
BaseCtrl
,控制器主要負責:
頁面交互邏輯(按鈕點擊、數據更新等)
與服務器、數據層的交互
接收用戶操作、修改視圖
控制器內部通常引用它的
PageInfo
和BaseView
。
3.BaseView
:視圖(表現層)視圖負責:
加載 UI 元素
控制 UI 的顯示/隱藏、動效
響應控制器的命令
視圖綁定在 prefab(預制體)上,顯示在屏幕上。你可以在
InitRoot()
中綁定 UI 組件:view.m_Panel = showPage.gameObject.GetComponent<UIPanel>(); view.InitRoot(view.m_Panel.ui);
總結整體結構圖
UIMgr(單例管理器) ├── Dictionary<EPageType, PageInfo> m_Ctrls // 當前顯示頁面 ├── Dictionary<EPageType, PageInfo> m_Caches // 緩存頁面 │ ├── PageInfo(頁面信息) │ ├── EPageType m_PageType │ ├── BaseCtrl m_Ctrl │ └── BaseView m_View │ ├── BaseCtrl(控制器) │ └── 控制邏輯、處理事件、更新視圖 │ └── BaseView(視圖)└── 處理 UI 表現、動畫、組件顯示
BaseCtrl & BaseView 是什么?職責劃分?
在 UI 框架中,通常采用 MVC(Model-View-Controller) 或其變種的架構思想。
BaseCtrl
和BaseView
,分別承擔:
類名 角色 職責 BaseCtrl
Controller 控制器,負責邏輯處理、按鈕響應、事件綁定、數據驅動等 BaseView
View 視圖,負責界面元素展示、動畫、UI 的顯示隱藏等視覺內容
它們共同組成了一個頁面(PageInfo
)的核心功能組合:PageInfo.m_Ctrl => 邏輯處理器 PageInfo.m_View => UI視圖渲染器
這種設計符合高內聚、低耦合的原則。
二、繼承結構概覽(類圖)[BaseCtrl] <--- [ShopCtrl] / [MainCtrl] / [BagCtrl] ... [BaseView] <--- [ShopView] / [MainView] / [BagView] ...