遊戲UI框架設計(二) 緩存
--最簡版本設計網絡
爲下降難度決定先講解一個最簡版本,闡述UI框架的核心設計理念。這裏先定義三個核心功能:框架
1:UI窗體的自動加載功能。ide
2:緩存UI窗體。測試
3:窗體生命週期(狀態)管理。ui
UI框架設計主要目的,就是儘量的完成一些與具體遊戲功能邏輯無關的一些底層事務性的功能實現。這些功能最好是自動或者是半自動的實現,無須客戶程序(調用框架的程序)再去過多處理與關心。
this
對於以上功能,筆者定義了UI框架的相關四個核心類:spa
在SysDefine 文件中,定義本框架三個核心枚舉類型設計
1 //UI窗體(位置)類型 2 public enum UIFormType 3 { 4 //普通窗體 5 Normal, 6 //固定窗體 7 Fixed, 8 //彈出窗體 9 PopUp 10 } 11 12 //UI窗體的顯示類型 13 public enum UIFormShowMode 14 { 15 //普通 16 Normal, 17 //反向切換 18 ReverseChange, 19 //隱藏其餘 20 HideOther 21 } 22 23 //UI窗體透明度類型 24 public enum UIFormLucenyType 25 { 26 //徹底透明,不能穿透 27 Lucency, 28 //半透明,不能穿透 29 Translucence, 30 //低透明度,不能穿透 31 ImPenetrable, 32 //能夠穿透 33 Pentrate 34 }
上述三個核心枚舉類型,解釋以下:code
上圖是咱們定義的UGUI 中的「根窗體」預設 "Canvas",在Untiy的層級視圖中,能夠看到咱們定義了若干空節點,用於不一樣類型的UI窗體加載到不一樣的「根窗體」預設中,實現不一樣顯示效果。
定義 UIType 類,主要是引用定義的三個核心枚舉,方便使用 。代碼以下:
1 /// <summary> 2 /// UI(窗體)類型 3 /// </summary> 4 internal class UIType 5 { 6 //是否須要清空「反向切換」 7 public bool IsClearReverseChange = false; 8 //UI窗體類型 9 public UIFormsType UIForms_Type = UIFormsType.Normal; 10 //UI窗體顯示類型 11 public UIFormsShowMode UIForms_ShowMode = UIFormsShowMode.Normal; 12 //UI窗體透明度類型 13 public UIFormsLucencyType UIForms_LucencyType = UIFormsLucencyType.Lucency; 14 }
定義基礎UI窗體 BaseUIForms 腳本,代碼以下:
1 public class BaseUIForms : MonoBehaviour 2 { 3 /* 字段 */ 4 //當前(基類)窗口的類型 5 private UIType _CurrentUIType=new UIType(); 6 7 /* 屬性 */ 8 /// <summary> 9 /// 屬性_當前UI窗體類型 10 /// </summary> 11 internal UIType CurrentUIType 12 { 13 set 14 { 15 _CurrentUIType = value; 16 } 17 18 get 19 { 20 return _CurrentUIType; 21 } 22 } 23 24 //頁面顯示 25 public virtual void Display() 26 { 27 this.gameObject.SetActive(true); 28 } 29 30 //頁面隱藏(不在「棧」集合中) 31 public virtual void Hiding() 32 { 33 this.gameObject.SetActive(false); 34 } 35 //頁面從新顯示 36 public virtual void Redisplay() 37 { 38 this.gameObject.SetActive(true); 39 } 40 //頁面凍結(還在「棧」集合中) 41 public virtual void Freeze() 42 { 43 this.gameObject.SetActive(true); 44 } 45 46 }//Class_end
上述代碼中,主要定義了UI窗體基類的四個重要虛方法,分別對應窗體的打開顯示、隱藏、從新顯示、窗體凍結(即:窗體顯示在其餘窗體下面)。方便窗體在不一樣狀態下,針對不一樣的行爲進一步作處理操做。例如,當窗體爲「隱藏」與「凍結」狀態時,若是此窗體有針對遠程服務的網絡鏈接(Socket套接字)時,則須要關閉網絡鏈接,以節省網絡資源。
定義「UI管理器」(UIManager.cs) 腳本,這是UI框架中的核心腳本,主要負責UI窗體的加載、緩存、以及對於「UI窗體基類」的各類生命週期的操做(顯示、隱藏、從新顯示、凍結)。
1 public class UIManager : MonoBehaviour { 2 /* 字段 */ 3 private static UIManager _Instance = null; 4 //UI窗體預設路徑(參數1:窗體預設名稱,2:表示窗體預設路徑) 5 private Dictionary<string, string> _DicFormsPaths; 6 //緩存全部UI窗體 7 private Dictionary<string, BaseUIForm> _DicALLUIForms; 8 //當前顯示的UI窗體 9 private Dictionary<string, BaseUIForm> _DicCurrentShowUIForms; 10 //UI根節點 11 private Transform _TraCanvasTransfrom = null; 12 //全屏幕顯示的節點 13 private Transform _TraNormal = null; 14 //固定顯示的節點 15 private Transform _TraFixed = null; 16 //彈出節點 17 private Transform _TraPopUp = null; 18 //UI管理腳本的節點 19 private Transform _TraUIScripts = null; 20 21 22 /// <summary> 23 /// 獲得實例 24 /// </summary> 25 /// <returns></returns> 26 public static UIManager GetInstance() 27 { 28 if (_Instance==null) 29 { 30 _Instance = new GameObject("_UIManager").AddComponent<UIManager>(); 31 } 32 return _Instance; 33 } 34 35 //初始化核心數據,加載「UI窗體路徑」到集合中。 36 public void Awake() 37 { 38 //字段初始化 39 _DicALLUIForms=new Dictionary<string, BaseUIForm>(); 40 _DicCurrentShowUIForms=new Dictionary<string, BaseUIForm>(); 41 _DicFormsPaths=new Dictionary<string, string>(); 42 //初始化加載(根UI窗體)Canvas預設 43 InitRootCanvasLoading(); 44 //獲得UI根節點、全屏節點、固定節點、彈出節點 45 _TraCanvasTransfrom = GameObject.FindGameObjectWithTag(SysDefine.SYS_TAG_CANVAS).transform; 46 _TraNormal = _TraCanvasTransfrom.Find("Normal"); 47 _TraFixed = _TraCanvasTransfrom.Find("Fixed"); 48 _TraPopUp = _TraCanvasTransfrom.Find("PopUp"); 49 _TraUIScripts = _TraCanvasTransfrom.Find("_ScriptMgr"); 50 //把本腳本做爲「根UI窗體」的子節點。 51 this.gameObject.transform.SetParent(_TraUIScripts, false); 52 //"根UI窗體"在場景轉換的時候,不容許銷燬 53 DontDestroyOnLoad(_TraCanvasTransfrom); 54 //初始化「UI窗體預設」路徑數據 55 //先寫簡單的,後面咱們使用Json作配置文件,來完善。 56 if (_DicFormsPaths!=null) 57 { 58 _DicFormsPaths.Add("LogonUIForm", @"UIPrefabs\LogonUIForm"); 59 } 60 } 61 62 /// <summary> 63 /// 顯示(打開)UI窗體 64 /// 功能: 65 /// 1: 根據UI窗體的名稱,加載到「全部UI窗體」緩存集合中 66 /// 2: 根據不一樣的UI窗體的「顯示模式」,分別做不一樣的加載處理 67 /// </summary> 68 /// <param name="uiFormName">UI窗體預設的名稱</param> 69 public void ShowUIForms(string uiFormName) 70 { 71 BaseUIForm baseUIForms=null; //UI窗體基類 72 73 //參數的檢查 74 if (string.IsNullOrEmpty(uiFormName)) return; 75 //根據UI窗體的名稱,加載到「全部UI窗體」緩存集合中 76 baseUIForms = LoadFormsToAllUIFormsCatch(uiFormName); 77 if (baseUIForms == null) return; 78 //根據不一樣的UI窗體的顯示模式,分別做不一樣的加載處理 79 switch (baseUIForms.CurrentUIType.UIForms_ShowMode) 80 { 81 case UIFormShowMode.Normal: //「普通顯示」窗口模式 82 //把當前窗體加載到「當前窗體」集合中。 83 LoadUIToCurrentCache(uiFormName); 84 break; 85 case UIFormShowMode.ReverseChange: //須要「反向切換」窗口模式 86 //更靠後課程進行講解。 87 break; 88 case UIFormShowMode.HideOther: //「隱藏其餘」窗口模式 89 //更靠後課程進行講解。 90 break; 91 default: 92 break; 93 } 94 } 95 96 #region 私有方法 97 //初始化加載(根UI窗體)Canvas預設 98 private void InitRootCanvasLoading() 99 { 100 ResourcesMgr.GetInstance().LoadAsset(SysDefine.SYS_PATH_CANVAS, false); 101 } 102 103 /// <summary> 104 /// 根據UI窗體的名稱,加載到「全部UI窗體」緩存集合中 105 /// 功能: 檢查「全部UI窗體」集合中,是否已經加載過,不然才加載。 106 /// </summary> 107 /// <param name="uiFormsName">UI窗體(預設)的名稱</param> 108 /// <returns></returns> 109 private BaseUIForm LoadFormsToAllUIFormsCatch(string uiFormsName) 110 { 111 BaseUIForm baseUIResult = null; //加載的返回UI窗體基類 112 113 _DicALLUIForms.TryGetValue(uiFormsName, out baseUIResult); 114 if (baseUIResult==null) 115 { 116 //加載指定名稱的「UI窗體」 117 baseUIResult = LoadUIForm(uiFormsName); 118 } 119 120 return baseUIResult; 121 } 122 123 /// <summary> 124 /// 加載指定名稱的「UI窗體」 125 /// 功能: 126 /// 1:根據「UI窗體名稱」,加載預設克隆體。 127 /// 2:根據不一樣預設克隆體中帶的腳本中不一樣的「位置信息」,加載到「根窗體」下不一樣的節點。 128 /// 3:隱藏剛建立的UI克隆體。 129 /// 4:把克隆體,加入到「全部UI窗體」(緩存)集合中。 130 /// 131 /// </summary> 132 /// <param name="uiFormName">UI窗體名稱</param> 133 private BaseUIForm LoadUIForm(string uiFormName) 134 { 135 string strUIFormPaths = null; //UI窗體路徑 136 GameObject goCloneUIPrefabs = null; //建立的UI克隆體預設 137 BaseUIForm baseUiForm=null; //窗體基類 138 139 140 //根據UI窗體名稱,獲得對應的加載路徑 141 _DicFormsPaths.TryGetValue(uiFormName, out strUIFormPaths); 142 //根據「UI窗體名稱」,加載「預設克隆體」 143 if (!string.IsNullOrEmpty(strUIFormPaths)) 144 { 145 goCloneUIPrefabs = ResourcesMgr.GetInstance().LoadAsset(strUIFormPaths, false); 146 } 147 //設置「UI克隆體」的父節點(根據克隆體中帶的腳本中不一樣的「位置信息」) 148 if (_TraCanvasTransfrom != null && goCloneUIPrefabs != null) 149 { 150 baseUiForm = goCloneUIPrefabs.GetComponent<BaseUIForm>(); 151 if (baseUiForm == null) 152 { 153 Debug.Log("baseUiForm==null! ,請先確認窗體預設對象上是否加載了baseUIForm的子類腳本! 參數 uiFormName=" + uiFormName); 154 return null; 155 } 156 switch (baseUiForm.CurrentUIType.UIForms_Type) 157 { 158 case UIFormType.Normal: //普通窗體節點 159 goCloneUIPrefabs.transform.SetParent(_TraNormal, false); 160 break; 161 case UIFormType.Fixed: //固定窗體節點 162 goCloneUIPrefabs.transform.SetParent(_TraFixed, false); 163 break; 164 case UIFormType.PopUp: //彈出窗體節點 165 goCloneUIPrefabs.transform.SetParent(_TraPopUp, false); 166 break; 167 default: 168 break; 169 } 170 171 //設置隱藏 172 goCloneUIPrefabs.SetActive(false); 173 //把克隆體,加入到「全部UI窗體」(緩存)集合中。 174 _DicALLUIForms.Add(uiFormName, baseUiForm); 175 return baseUiForm; 176 } 177 else 178 { 179 Debug.Log("_TraCanvasTransfrom==null Or goCloneUIPrefabs==null!! ,Plese Check!, 參數uiFormName="+uiFormName); 180 } 181 182 Debug.Log("出現不能夠預估的錯誤,請檢查,參數 uiFormName="+uiFormName); 183 return null; 184 }//Mehtod_end 185 186 /// <summary> 187 /// 把當前窗體加載到「當前窗體」集合中 188 /// </summary> 189 /// <param name="uiFormName">窗體預設的名稱</param> 190 private void LoadUIToCurrentCache(string uiFormName) 191 { 192 BaseUIForm baseUiForm; //UI窗體基類 193 BaseUIForm baseUIFormFromAllCache; //從「全部窗體集合」中獲得的窗體 194 195 //若是「正在顯示」的集合中,存在整個UI窗體,則直接返回 196 _DicCurrentShowUIForms.TryGetValue(uiFormName, out baseUiForm); 197 if (baseUiForm != null) return; 198 //把當前窗體,加載到「正在顯示」集合中 199 _DicALLUIForms.TryGetValue(uiFormName, out baseUIFormFromAllCache); 200 if (baseUIFormFromAllCache!=null) 201 { 202 _DicCurrentShowUIForms.Add(uiFormName, baseUIFormFromAllCache); 203 baseUIFormFromAllCache.Display(); //顯示當前窗體 204 } 205 } 206 207 #endregion 208 209 }//class_end
UI管理器腳本解釋以下:
一:上述代碼中重要字段的解釋以下:
1: 「_DicFormsPaths」 表示「UI窗體預設路徑」集合,負責緩存全部UI窗體預設的名稱與對應資源路徑的關係。
2: 「 _DicALLUIForms」 表示「全部UI窗體」集合,負責緩存已經加載過的全部UI窗體名稱以及與之對應的UI窗體。
3: 「_DicCurrentShowUIForms」表示「當前正在顯示」集合,負責控制正在顯示UI窗體的內部邏輯。
4: UI管理器腳本中的「_TraCanvasTransfrom」、「_TraNormal」、「_TraFixed」、「_TraPopUp」、「_TraUIScripts」,分別表示Unity層級視圖中的根結點、普通節點、固定節點、彈出節點、管理腳本節點,這些節點是加載UI窗體的不一樣類型的父節點,用於各類UI窗體的管理工做。
二:上述代碼中重要方法的解釋以下:
1: ShowUIForms() 是外部程序調用本框架的對外公共方法,負責加載、緩存、打開與顯示制定窗體名稱的UI窗體預設。
2: LoadFormsToAllUIFormsCatch() 是根據UI窗體的名稱,加載到「全部UI窗體」緩存集合中。
3: LoadUIToCurrentCache() 是把當前窗體加載到「當前窗體」集合中。
上述(UI框架)腳本編寫完畢,測試成功後效果以下圖:
爲廣大讀者進一步瞭解與熟悉本框架,特提供下載連接:https://pan.baidu.com/s/1eTA8rHS 密碼:4x6e
本篇就先寫到這,下篇 "遊戲UI框架設計(3)_窗體的層級管理" 繼續。