項目開發日記

框架整理學習

UIMgr:

一、數據結構與算法
1.1 關鍵數據結構

成員變量類型說明
m_CtrlsList<PageInfo>當前正在顯示的所有 UI 頁面
m_CachesList<PageInfo>已打開過、但現在不顯示的頁面(緩存池)
1.2 算法邏輯
  • 查找緩存頁面:從 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 組件,并手動獲取并設置 BaseCtrlBaseView


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_Ctrlsm_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 “時間換空間”?

? 空間換時間

意思是:通過多占用內存空間,來提升運行效率(尤其是查找效率)

例如:

  • 創建一個大型的數組或哈希表,快速定位數據。

  • 為了加快訪問速度,犧牲一些內存來保存冗余數據或索引。

    ? 時間換空間

    意思是:通過減少內存占用,但犧牲一點運行效率(特別是遍歷或查找速度)

    例如:

  • 僅保存最少必要信息,每次都從頭計算或查找。

  • 不額外保存中間狀態,減少內存消耗。

    二、對比 DictionaryList

    特性Dictionary<K, V>List<T>
    本質結構哈希表(Hash Table)數組(Array)
    查找效率O(1) 常數時間(哈希定位)O(n) 線性時間(需要遍歷整個列表)
    插入效率快,但哈希沖突時略慢尾部插入快,插入中間則可能慢
    占用內存:維護哈希表結構、桶數組等:僅維護數據本身
    是否保證順序不保證插入順序保證插入順序
    使用場景快速定位、查找、映射(如字典、緩存系統)順序存儲、小集合、頻繁遍歷
    三、空間換時間的例子(Dictionary)
    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 是“時間換空間”內存占用少,但每次操作如查找需要從頭遍歷,適合數據量小、頻繁順序處理的場景

?PageInfoBaseCtrlBaseView 是什么?作用是什么?

1. PageInfo:頁面的容器(頁面元信息)

PageInfo 主要負責綁定以下三件事:

  • 頁面類型 EPageType

  • 控制器組件 BaseCtrl

  • 視圖組件 BaseView

  • UI 面板 UIPanel(來自 FairyGUI)

  • gameObject 對象本身

它像是一個頁面的數據模型,保存了一切有關這個 UI 頁面的運行時數據。

2. BaseCtrl:控制器(邏輯層)

所有頁面控制器都應該繼承自 BaseCtrl,控制器主要負責:

  • 頁面交互邏輯(按鈕點擊、數據更新等)

  • 與服務器、數據層的交互

  • 接收用戶操作、修改視圖

控制器內部通常引用它的 PageInfoBaseView


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) 或其變種的架構思想。
BaseCtrlBaseView,分別承擔:

類名角色職責
BaseCtrlController控制器,負責邏輯處理、按鈕響應、事件綁定、數據驅動等
BaseViewView視圖,負責界面元素展示、動畫、UI 的顯示隱藏等視覺內容

它們共同組成了一個頁面(PageInfo)的核心功能組合:
PageInfo.m_Ctrl => 邏輯處理器
PageInfo.m_View => UI視圖渲染器

這種設計符合高內聚、低耦合的原則。

二、繼承結構概覽(類圖)

[BaseCtrl] <--- [ShopCtrl] / [MainCtrl] / [BagCtrl] ...
[BaseView] <--- [ShopView] / [MainView] / [BagView] ...

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/88575.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/88575.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/88575.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

60 美元玩轉 Li-Fi —— 開源 OpenVLC 平臺入門(附 BeagleBone Black 驅動簡單解析)

60 美元玩轉 Li-Fi —— 開源 OpenVLC 平臺入門&#xff08;附 BeagleBone Black 及驅動解析&#xff09;一、什么是 OpenVLC&#xff1f; OpenVLC 是由西班牙 IMDEA Networks 研究所推出的開源可見光通信&#xff08;VLC / Li-Fi&#xff09;研究平臺。它把硬件、驅動、協議棧…

Python性能優化

Python 以其簡潔和易用性著稱,但在某些計算密集型或大數據處理場景下,性能可能成為瓶頸。幸運的是,通過一些巧妙的編程技巧,我們可以顯著提升Python代碼的執行效率。本文將介紹8個實用的性能優化技巧,幫助你編寫更快、更高效的Python代碼。   一、優化前的黃金法則:先測…

easyui碰到想要去除頂部欄按鈕邊框

只需要加上 plain"true"<a href"javascript:void(0)" class"easyui-linkbutton" iconCls"icon-add" plain"true"onclick"newCheck()">新增</a>

C++字符串詳解:原理、操作及力扣算法實戰

一、C字符串簡介在C中&#xff0c;字符串的處理方式主要有兩種&#xff1a;字符數組&#xff08;C風格字符串&#xff09;和std::string類。雖然字符數組是C語言遺留的底層實現方式&#xff0c;但現代C更推薦使用std::string類&#xff0c;其封裝了復雜的操作邏輯&#xff0c;提…

CMU15445-2024fall-project1踩坑經歷

p1目錄&#xff1a;lRU\_K替換策略LRULRU\_K大體思路SetEvictableRecordAccessSizeEvictRemoveDisk SchedulerBufferPoolNewPageDeletePageFlashPage/FlashAllPageCheckReadPage/CheckWritePagePageGuard并發設計主邏輯感謝CMU的教授們給我們分享了如此精彩的一門課程&#xff…

【C語言進階】帶你由淺入深了解指針【第四期】:數組指針的應用、介紹函數指針

前言上一期講了數組指針的原理&#xff0c;這一期接著上一期講述數組指針的應用以及數組參數、函數參數。首先看下面的代碼進行上一期內容的復習&#xff0c;pc應該是什么類型&#xff1f;char* arr[5] {0}; xxx pc &arr;分析&#xff1a;①首先判斷arr是一個數組&#x…

在HTML中CSS三種使用方式

一、行內樣式在標簽<>中輸入style "屬性&#xff1a;屬性值;"。(中等使用頻率)不利于CSS樣式的復用&#xff1b;違背了CSS內容和樣式分離的設計理念&#xff0c;后期難以維護。<p style"color: red">這是div中的p元素</p>二、內部樣式在…

汽車功能安全-軟件單元驗證 (Software Unit Verification)【用例導出方法、輸出物】8

文章目錄1 軟件單元驗證用例導出方法2 測試用例完整性度量標準3 驗證環境要求4 軟件單元驗證的工作產品1 軟件單元驗證用例導出方法 為確保軟件單元測試的測試案例規范符合9.4.2要求&#xff0c;應通過表8所列方法開發測試用例。 表8 軟件單元測試用例的得出方法&#xff1a; …

MySQL內置函數(8)

文章目錄前言一、日期函數二、字符串函數三、數學函數四、其它函數總結前言 其實在之前的幾篇中我們也用到了內置函數&#xff0c;現在我們再來系統學習一下它&#xff01; 一、日期函數 函數名稱描述current_date()獲取當前日期current_time()獲取當前時間current_timestamp(…

蒼穹外賣項目日記(day04)

蒼穹外賣|項目日記(day04) 前言: 今天主要是接口開發, 涉及的新東西不多, 需要注意的只有多表聯查和修改的邏輯,今日難點: 1.菜品的停起售狀態設置 2.套餐的停起售狀態設置 3.動態sql中的 useGeneratedKeys 與 keyProperty 兩個參數 一. 菜品的停起售狀態設置 ? 在菜品的停售中…

React之旅-05 List Key

每個React的初學者&#xff0c;在調試程序時&#xff0c;都會遇到這樣的警告&#xff1a;Warning: Each child in a list should have a unique "key" prop. 如下面的代碼&#xff1a; const list [Learn React, Learn GraphQL];const ListWithoutKey () > (&l…

[特殊字符] 人工智能技術全景:從基礎理論到前沿應用的深度解析

&#x1f680; 人工智能技術全景&#xff1a;從基礎理論到前沿應用的深度解析 在這個AI驅動的時代&#xff0c;理解人工智能的核心技術和應用場景已成為技術人員的必備技能。本文將帶你深入探索AI的發展脈絡、核心技術差異以及在各行業的創新應用。 文章目錄&#x1f680; 人工…

Go語言教程-環境搭建

前言 Go&#xff08;又稱 Golang&#xff09;是由 Google 開發的一種 開源、靜態類型、編譯型 編程語言&#xff0c;于 2009 年正式發布。它旨在解決現代軟件開發中的高并發、高性能和可維護性問題&#xff0c;尤其適合 云計算、微服務、分布式系統 等領域。 Go 語言國際官網…

windows指定某node及npm版本下載

下載并安裝 nvm-windowshttps://github.com/coreybutler/nvm-windows/releases&#xff08;選擇 nvm-setup.zip&#xff09;。打開命令提示符&#xff08;管理員權限&#xff09;&#xff0c;安裝 Node.js v16.15.0&#xff1a; nvm install 16.15.0 nvm use 16.15.0 驗證node版…

每天一個前端小知識 Day 28 - Web Workers / 多線程模型在前端中的應用實踐

Web Workers / 多線程模型在前端中的應用實踐&#x1f9e0; 一、為什么前端需要多線程&#xff1f; 單線程 JS 的瓶頸&#xff1a;瀏覽器主線程不僅負責執行 JS&#xff0c;還要負責&#xff1a; UI 渲染&#xff08;DOM/CSS&#xff09;用戶事件處理&#xff08;點擊、輸入&am…

python:ImportError: cannot import name ‘ParameterSource‘ from ‘click.core‘

瀏覽器訪問網站拋錯&#xff1a;ImportError: cannot import name ParameterSource from click.core (E:\environment\python\Lib\site-packages\click\core.py)問題分析&#xff1a;1. click 版本問題ParameterSource 可能是在某個特定版本的 click 庫中引入的&#xff0c;而你…

flink 去重

LOCALTIMESTAMP as time_stamp ts as case when time is null then CURRENT_TIMESTAMP else TO_TIMESTAMP_LTZ(time, 0) end , watermark for ts as ts - interval ‘60’ second PARTITION BY 的都有回撤流 group by 的沒有回撤流 因為算的是指標 開窗又慢 SELECT * FROM (…

【音視頻】TS協議解析

參考博客&#xff1a;https://blog.csdn.net/rell336/article/details/38109621?utm_mediumdistribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.channel_param&depth_1-utm_sourcedistribute.pc_relevant_t0.none-task-blog-BlogCommendFromMac…

uniapp 日期組件可選擇年月

month-picker 月份選擇器組件 組件介紹 month-picker 是一個用于選擇年月的自定義組件&#xff0c;基于 uni-app 開發&#xff0c;提供了簡潔的月份選擇功能。 解決彈框底部出現底部頁面區域 safe-area屬性設為true時&#xff0c;即可解決這個問題效果如圖功能特點 支持選擇年份…

從真人到數字分身:3D人臉掃描設備在高校數字人建模教學中的應用

在影視、動漫、游戲等數字創意產業蓬勃發展的當下&#xff0c;超寫實虛擬數字人憑借其高度逼真的形象&#xff0c;成為行業關注的焦點。無論是影視特效中栩栩如生的角色&#xff0c;還是游戲里精致的NPC&#xff0c;超寫實虛擬數字人的制作都離不開先進的技術支撐。而3D人臉掃描…