游戲開發學習記錄

初始化只是第一次實例化的時候調用,show和unshow是打開界面和關閉界面的時候,會多次調用
在一個腳本里面show是每一次打開界面的時候需要做的事情,而Init是初始化。

UIMgr里面的數據結構:

為什么我要先從數據結構入手呢?因為程序 = 數據結構 + 算法!!!!!!

UIMgr(UI 管理器),用于管理游戲中打開、關閉、緩存 UI 頁面,屬于典型的 MVC(Model-View-Controller)架構中的 View 管理層

List<PageInfo> m_Ctrls —— 當前正在顯示的頁面列表

  • 類型:List<PageInfo>

  • 用途:保存當前正在顯示(激活)的頁面。

  • 特性:打開時添加,關閉時移除。

?List<PageInfo> m_Caches —— 已經關閉但緩存的頁面

  • 類型:List<PageInfo>

  • 用途:用作“對象池”,防止 UI 頁面重復加載。

  • 特性:關閉后放入緩存,下次打開優先從緩存中取。

UIMgr(UI管理器)

├── PageInfo ?// 每個頁面的信息,包含 Ctrl 和 View
│ ? ├── m_PageType : EPageType ? ? ?// 頁面枚舉
│ ? ├── m_Ctrl : BaseCtrl ? ? ? ? ? // 控制器邏輯
│ ? ├── m_View : BaseView ? ? ? ? ? // UI 視圖
│ ? ├── m_IsOpen : bool ? ? ? ? ? ? // 當前是否打開

├── BaseCtrl(控制器)
│ ? ├── Init() / Show() / UnShow() ?// 控制邏輯
│ ? ├── m_PageInfo : PageInfo

├── BaseView(UI顯示層)
│ ? ├── Init() / Show() / UnShow() ?// 視覺表現
│ ? ├── m_PageInfo : PageInfo
│ ? ├── m_Panel : UIPanel ? ? ? ? ? // FairyGUI UI根

核心算法流程:

一.打開頁面(OpenPage(EPageType type)

輸入:EPageType(頁面類型枚舉)

算法流程:
1. 檢查是否已經在打開中(m_Ctrls 中查找)
2. 如果緩存中有(m_Caches 中查找),直接復用(緩存指的是“已經關閉但沒有銷毀的頁面實例”,用于復用,避免重復創建,提高性能。
3. 如果沒有,就創建新頁面
- 加載資源(從路徑映射表中查路徑)
- 掛載 PageInfo、BaseCtrl、BaseView、UIPanel
- 初始化 Ctrl 與 View

4. 添加到當前頁面列表 m_Ctrls
5. 顯示 Ctrl 和 View


二.關閉頁面 closePage()

????????

輸入:可以是 EPageType / PageInfo / BaseCtrl / BaseView

算法流程:
1. 設置頁面狀態為關閉
2. 調用 Ctrl 和 View 的隱藏方法(帶或不帶動畫)
3. 從 m_Ctrls 中移除
4. 添加到 m_Caches(復用池)
5. 廣播事件通知 UI 被關閉

三.重新刷新頁面 RefreshCurPage()

1. 取出棧頂頁面(最后一個 m_Ctrls)
2. 關閉它
3. 再打開它(重新加載或從緩存中恢復)

四.同時關閉并打開新頁面(CloseAndOpenPage)

1. 先關閉傳入的舊頁面(PageInfo 或 BaseCtrl)
2. 再打開新的頁面

五.查找指定頁面信息

PageInfo GetPageInfo(EPageType type)
遍歷 m_Ctrls,找到匹配頁面類型的 PageInfo



eg:

打開背包頁面時,OpenPage(EPageType.BagPage) 會:

  1. 檢查當前 UI 中是否已經有 BagPage

  2. 沒有則加載資源,例如 "UI/BagPanel"

  3. 實例化組件,掛載腳本

  4. 添加到 m_Ctrls 列表

  5. 展示 UI 視圖

關閉時會反過來處理。

C#基礎語法
語法點示例建議學習關鍵詞
類繼承: Singleton<UIMgr>泛型繼承、泛型類
構造函數保護protected override void OnInit()虛方法、重寫
泛型方法GetPageCtrl<T>() where T : BaseCtrl泛型約束
集合操作List<PageInfo>.Add/Remove集合遍歷、倒序遍歷
條件判斷if / else / return分支語句
循環for / foreach倒序刪除元素的寫法
類型轉換as PlayerEvt, as T類型安全轉換
組件操作AddComponent<>(), GetComponent<>()Unity / FairyGUI 組件獲取
字典操作TryGetValue()Dictionary 用法
日志打印MyLogger.Info()打印調試工具類
枚舉EPageType枚舉類型使用

基礎語法回顧

什么是泛型?
泛型(Generic)是為類或方法指定“類型參數的一種機制。可以讓你的代碼更通用、可復用,而且類型安全

泛型類型示例:

public class Box<T>
{public T Content;public void Print(){Console.WriteLine(Content);}
}

使用方法:

Box<string> box1 = new Box<string>();
box1.Content = "Hello";Box<int> box2 = new Box<int>();
box2.Content = 123;

泛型方法示例:

public class Printer
{public void Print<T>(T value){Console.WriteLine(value);}
}

調用方式:

Printer p = new Printer();
p.Print("文字");
p.Print(100);

泛型約束:

public T GetPageCtrl<T>(EPageType ePageType) where T : BaseCtrl

這表示 T 必須繼承自 BaseCtrl,否則編譯報錯。這叫泛型約束

List倒序刪除元素
為什么要倒序刪除?
因為如果你正序刪除索引會移動容易漏刪或報錯。

如下寫法:

for (int i = list.Count - 1; i >= 0; i--)
{if (list[i] == 條件){list.RemoveAt(i);}
}


C# override 和 base 的區別

override是重寫父類方法

public class Base
{public virtual void Speak(){Console.WriteLine("Base speaking");}
}public class Child : Base
{public override void Speak(){Console.WriteLine("Child speaking");}
}


base是調用父類方法

public override void Speak()
{base.Speak();  // 先調用父類邏輯Console.WriteLine("Child speaking");
}

你可以理解為:

  • override: 我要覆蓋父類行為

  • base: 我要在子類中繼續使用父類行為

什么是MVC架構

MVC是什么?

MVC 全稱:Model - View - Controller
是一種軟件架構模式,用于分離數據、界面與邏輯提高可維護性與模塊化

如我的UIMgr里面的MVC架構:

組件作用示例類
Model數據DataMgr, ItemData
View界面顯示BaseView, UIPanel
Controller控制邏輯BaseCtrl
MVC示意圖:


  • Controller 連接用戶輸入與業務邏輯

  • View 專注展示 UI,不處理邏輯

  • Model 是純數據(如道具表、角色數據)

UIPanel是什么?

FairyGUI 中,UIPanel掛在 GameObject 上的 UI 容器組件,用于將 FGUI 的 UI 顯示在 Unity 場景中。

用法說明:

UIPanel panel = go.GetComponent<UIPanel>();
panel.ui = UIPackage.CreateObject("包名", "組件名") as GComponent;
  • UIPanel.ui:是一個 FGUI 的 GComponent,就是 UI 根節點

  • 每個頁面視圖(BaseView)都掛在這個 panel 上操作

GetComponent<T>()如何用?

Unity 中常用來獲取掛載在 GameObject 上的組件腳本

示例:

// 獲取自身掛載的 BoxCollider
BoxCollider box = gameObject.GetComponent<BoxCollider>();// 獲取子物體上掛載的 BaseView
BaseView view = transform.Find("Child").GetComponent<BaseView>();


常見錯誤:

// 錯誤:可能 GameObject 上沒有這個組件
var view = go.GetComponent<BaseView>();
if (view == null) Debug.Log("沒有找到組件!");


?如何異步加載UI?

Unity 中 UI 面板如果太大,推薦異步加載資源文件,以防卡頓。


簡單異步加載方式(基于 Addressables 或 Resources

IEnumerator LoadUI(string path, Action<GameObject> callback)
{ResourceRequest request = Resources.LoadAsync<GameObject>(path);yield return request;GameObject obj = GameObject.Instantiate(request.asset as GameObject);callback?.Invoke(obj);
}

調用方式:

StartCoroutine(LoadUI("UIPrefab/Bag", (ui) => {// 初始化邏輯
}));

總結
關鍵詞用途重點
泛型類與方法復用,帶類型限制T, where T : BaseCtrl
List 倒序刪除避免刪除錯位for (i = Count - 1; i--)
override/base子類覆蓋/調用父類方法多態
MVC分離邏輯/界面/數據架構思想
UIPanelFairyGUI 與 Unity 橋梁ui = GComponent
GetComponent獲取組件類型匹配注意空檢查
異步加載防止 UI 卡頓Resources.LoadAsync, Addressables

緩存?
緩存指的是“已經關閉但沒有銷毀的頁面實例”,用于復用,避免重復創建,提高性能。

List<PageInfo> m_Caches;

保留在內存中,放入緩存列表中,等下次打開時直接復用。

原因說明
🚀 提高性能打開/關閉頁面頻繁,如果每次都加載資源、實例化,會卡頓、浪費性能
🧠 減少 GC避免頻繁創建銷毀對象帶來的垃圾回收
?? 加快響應速度從緩存中復用 UI 頁面幾乎是瞬間完成的

緩存邏輯是如何運作的?

1.打開頁面時?
OpenPage(EPageType type)

// 先檢查緩存列表
PageInfo pageInfo = GetCachePage(type);
if (pageInfo != null)
{// 從緩存恢復m_Caches.Remove(pageInfo);m_Ctrls.Add(pageInfo);pageInfo.m_Ctrl.Show();pageInfo.m_View.Show();
}

2.關閉頁面時 Close Page(Page InfopageInfo):

pageInfo.m_IsOpen = false;// 隱藏,但不銷毀
pageInfo.m_Ctrl.UnShow();
pageInfo.m_View.UnShow();// 從顯示列表中移除
m_Ctrls.Remove(pageInfo);// 加入緩存列表
m_Caches.Add(pageInfo);

示意圖:頁面狀態轉換



類似現實中:

想象你是個餐館老板:

  • 顧客來了:你先看看有沒有空桌子(緩存)

  • 沒有就新擺一張桌子(創建新的頁面)

  • 顧客走了,你不收桌子,只是讓它暫時閑置,等下個顧客再來用(放入緩存)


緩存的注意點:

  • UI 頁面狀態要正確重置(避免殘留上次數據)

  • 如果頁面太多,可能要設計LRU緩存策略(如保留最近 3 個頁面,其余銷毀)

  • 緩存列表不能太大,否則內存占用也會增加

    緩存是“已關閉但未銷毀的頁面”,用于下次快速復用,提高性能、減少加載。

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

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

相關文章

一級緩存與二級緩存深度剖析:作用域、配置與同步方案全解析

引言 在分布式系統與高并發場景下&#xff0c;緩存機制已成為提升系統性能的關鍵技術。本文從作用域、失效機制、配置實踐到同步方案&#xff0c;系統化解析一級緩存與二級緩存的核心差異與工程實踐。 一、一級緩存&#xff1a;會話級數據加速器 1.1 作用域與生命周期 作用域&a…

OneCode MQTT插件開發實戰:基于Paho.Client的物聯網通信解決方案

引言 在物聯網應用開發中&#xff0c;MQTT協議因其輕量、低帶寬占用的特性被廣泛采用。OneCode平臺提供的xui.MQTT插件基于Eclipse Paho.Client實現了完整的MQTT通信能力&#xff0c;本文將從插件用途、核心實現、開發要點和功能擴展四個維度&#xff0c;詳解如何基于該插件構建…

1.1_5_1 計算機網絡的性能指標(上)

在這個小節中我們要學習計算機網絡的性能指標&#xff0c;我們在考研當中主要掌握這樣的七個性能指標&#xff0c;分別是速率、帶寬、吞吐量、時延、時延帶寬積、往返時延和信道利用率。我會把相關性比較緊密的性能指標放在一起講解。在這個視頻中&#xff0c;我們先來學習前三…

Python 性能優化指南:深入剖析代碼分析與優化工具

Python 性能優化指南:深入剖析代碼分析與優化工具 在 Python 的廣泛應用場景中,性能優化既是挑戰,也是機遇。無論是構建 Web 應用還是處理數據分析,理解代碼性能瓶頸并有效優化至關重要。本文將探討 Python 代碼性能分析的核心方法,并逐步解析關鍵工具的使用技巧,帶您從…

力扣打卡第二十一天 中后遍歷+中前遍歷 構造二叉樹

106. 從中序與后序遍歷序列構造二叉樹 給定兩個整數數組 inorder 和 postorder &#xff0c;其中 inorder 是二叉樹的中序遍歷&#xff0c; postorder 是同一棵樹的后序遍歷&#xff0c;請你構造并返回這顆 二叉樹 。 示例 1: 輸入&#xff1a;inorder [9,3,15,20,7], postor…

Notepad++正則表達全解

摘要:Notepad正則表達式符號大全包含11類常用語法&#xff1a;基礎符號&#xff08;.^$?等&#xff09;、預定義字符類&#xff08;\d\w\s等&#xff09;、錨點&#xff08;\b\B&#xff09;、量詞&#xff08;{n,m}&#xff09;、分組引用&#xff08;()$1&#xff09;、字符…

前后端分離(java) 和 Nginx在服務器上的完整部署方案(redis、minio)

一、準備工作 服務器環境要求 銀河麒麟 V10 操作系統 開放端口&#xff1a;MinIO (9000、9001)、 Redis (6379)、應用服務 jar包(18888)、前端服務(8080) 系統用戶&#xff1a;具有 sudo 權限的用戶 操作&#xff1a;需要先有必備的工具前端的vsCode,webStrom、后臺的idea&…

貪心算法:簡單而高效的求解策略C++

貪心算法詳解及C實現 1. 什么是貪心算法 貪心算法&#xff08;Greedy Algorithm&#xff09;是一種在每一步選擇中都采取在當前狀態下最好或最優&#xff08;即最有利&#xff09;的選擇&#xff0c;從而希望導致結果是全局最好或最優的算法策略。 貪心算法與動態規劃不同在于它…

IDEA 中使用 <jsp:useBean>動作指令時,class屬性引用無效

問題&#xff1a;在 IDEA 中創建 Java Web項目&#xff0c;在src/model包下存在一個Student類該類中包含&#xff1a;全參構造器、私有屬性的get/set方法。然后在 jsp 頁面中使用 <jsp:useBean>創建Student類的對象&#xff1a;訪問頁面時報錯&#xff1a;原因&#xff1…

【網絡】Linux 內核優化實戰 - net.core.flow_limit_table_len

目錄參數作用查看與修改調優建議相關警告net.core.flow_limit_table_len 是 Linux 內核中的一個網絡參數&#xff0c;用于控制**流限制表&#xff08;Flow Limit Table&#xff09;**的大小。這個表主要用于限制網絡流量中單個"流"&#xff08;通常指來自同一源IP、端…

前端開發常見問題技術文章大綱

前端開發常見問題技術文章大綱 常見性能優化問題 頁面加載速度慢的原因及解決方案渲染阻塞資源的優化方法內存泄漏的檢測與修復 跨瀏覽器兼容性問題 不同瀏覽器對CSS和JavaScript的支持差異Polyfill和Shim的使用場景如何利用工具檢測兼容性問題 響應式設計挑戰 媒體查詢的最佳實…

Redis常見性能問題和解決方案有哪些?

Redis 作為高性能的內存數據庫&#xff0c;在實際使用中可能會遇到性能問題。以下是常見的性能問題及其解決方案&#xff0c;用中文總結如下&#xff1a; 1. 高延遲問題 問題描述&#xff1a;客戶端請求響應時間過長&#xff0c;可能由于網絡、命令復雜度或服務器負載導致。 解…

閃測儀應用案例丨手機中框如何突破「尺寸檢測」瓶頸?

越來越多的手機中框&#xff0c;正改為更復雜的鏤空設計&#xff0c;這種設計不僅保持了手機中框的結構強度&#xff0c;還進一步減輕了機身重量&#xff0c;同時提升了散熱性能。這讓手機中框的自動化生產增加了很多難點&#xff0c;其中的尺寸檢測就遇到了許多瓶頸。? 尺寸精…

【字節跳動】數據挖掘面試題0011:介紹下時間序列分析常用知識點

文章大綱時間序列分析全面解析一、時間序列分析的基本概念二、時間序列分析的主要方法1. 描述性分析2.統計分析方法3.預測模型&#xff08;1&#xff09;傳統統計模型&#xff08;2&#xff09;現代機器學習模型三、時間序列分析的應用場景四、模型評估五、在字節跳動的應用場景…

ubuntu中交叉編譯iperf3到目標平臺xilinx

注&#xff1a;此文為ubuntu x86系統編譯程序到xilinx aarch64系統中。 一、工具準備 x86上編譯aarch64的編譯器 sudo apt install gcc-aarch64-linux-gnu g-aarch64-linux-gnu #保證編譯器在環境變量中&#xff0c;嘗試執行aarch64-linux-gnu-gcc 目標平臺的根文件系統rootf…

Java-數據結構-集合框架

什么是集合框架集合本質是java所實現的一組數據結構&#xff0c;提供了不同的增刪改查方法。集合就是定義了接口&#xff0c;再通過不同的類去實現定義的接口&#xff0c;這些實現了接口的類就是集合類&#xff0c;例如list&#xff0c;stack&#xff0c;map。集合框架的重要性…

黑馬點評系列問題之基礎篇16jedis redis依賴引入后仍然還是報錯

問題描述依賴已經導入進去了&#xff0c;在倉庫里有***.jar和***.pom這兩個文件&#xff0c;但是點開右面的maven還是有很多爆紅。點擊maven里的更新還是不行。解決點到配置文件pom.xml在lombok這個依賴的代碼下面&#xff0c;添加上版本號&#xff0c;刷新一下右鍵單擊pom.xml…

SQL 一鍵轉 GORM 模型,支持字段注釋、類型映射、tag 自定義!

SQL 一鍵轉 GORM 模型&#xff0c;支持字段注釋、類型映射、tag 自定義&#xff01; 在使用 Golang GORM 開發項目時&#xff0c;你是否也經歷過這些「重復性痛苦」&#xff1a; ? 拿到建表 SQL&#xff0c;要手動寫 struct? 字段多、類型復雜&#xff0c;還要寫 json、go…

前端計算機視覺:使用 OpenCV.js 在瀏覽器中實現圖像處理

一、OpenCV.js 簡介與環境搭建OpenCV&#xff08;Open Source Computer Vision Library&#xff09;是一個強大的計算機視覺庫&#xff0c;廣泛應用于圖像和視頻處理領域。傳統上&#xff0c;OpenCV 主要在后端使用 Python 或 C 等語言。但隨著 WebAssembly (Wasm) 技術的發展&…

開發在線商店:基于Vue2+ElementUI的電商平臺前端實踐

Hi&#xff0c;我是布蘭妮甜 &#xff01;在當今數字化時代&#xff0c;電子商務已成為商業領域的重要組成部分。開發一個功能完善、用戶友好的在線商店應用對于企業拓展市場至關重要。本文將詳細介紹如何使用Vue2框架配合ElementUI組件庫開發一個完整的在線商店應用。 文章目錄…