遊戲UI框架設計(二) : 最簡版本設計

爲降低難度決定先講解一個最簡版本,闡述UI框架的核心設計理念。這裏先定義三個核心功能:

   1:UI窗體的自動加載功能。

   2:緩存UI窗體。

   3:窗體生命週期(狀態)管理。

     UI框架設計主要目的,就是儘可能的完成一些與具體遊戲功能邏輯無關的一些底層事務性的功能實現。這些功能最好是自動或者是半自動的實現,無須客戶程序(調用框架的程序)再去過多處理與關心。

    對於以上功能,筆者定義了UI框架的相關四個核心類:

  •    BaseUIForms    基礎UI窗體腳本(父類,其他窗體都繼承此腳本)
  •    UIManger.cs    UI窗體管理器腳本(框架核心腳本)
  •    UIType         窗體類型 (引用窗體的重要屬性[枚舉類型])
  •    SysDefine      系統定義類(包含框架中使用到的枚舉類型、委託事件、系統常量、接口等)

  在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     }
複製代碼

 

 上述三個核心枚舉類型,解釋如下:

  1.  UIFormType 枚舉類型,表示Unity層級視圖中掛載不同類型窗體的空節點。這裏Fixed 表示固定窗體,表示可以掛載"非全屏非彈出窗體",例如RPG遊戲項目中的“英雄信息”窗體等。
  2.  UIFormShowMode 枚舉,表示窗體不同的顯示方式。Normal 類型表示窗體與其他窗體可以並列顯示; HideOther類型表示窗體顯示的時候,需要隱藏所有其他窗體; ReverseChange 窗體主要應用與"彈出窗體",維護多個彈出窗體的層級關係。
  3.  UIFormLucenyType 枚舉,是定義彈出“模態窗體”不同透明度的類型。

  上圖是我們定義的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框架)腳本編寫完畢,測試成功後效果如下圖:

 

  爲廣大讀者進一步瞭解與熟悉本框架,特提供下載鏈接:http://pan.baidu.com/s/1skN2Njn 密碼:2ey6

發佈了6 篇原創文章 · 獲贊 11 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章