1. 程式人生 > >UI框架搭建DAY1

UI框架搭建DAY1

分析:UI框架主要是為了使用者(使用框架的程式猿)更快捷、方便地開發UI,UI框架的好處還在於解耦,使得程式更具有靈活性。

UI框架的核心是視窗的管理,視窗管理的主要任務就是顯示視窗和關閉視窗。

因為視窗的型別多樣,比如彈出式視窗,固定位置視窗,隱藏其他視窗(開啟這個視窗會覆蓋整個螢幕),模態視窗等等。

這裡我目前把視窗分為三大型別:普通視窗、彈出式視窗、隱藏其他視窗,而位置固定、是否模態作為視窗的屬性。

1.為了更易於複用和拓展,我設計了一個基類BasePanel, NormalPanel, PopupPanel, HiderOtherPanel都由此基類派生。

BasePanel封裝了3個重要方法:Open(), Close(), Freeze()。

2.巧婦難為無米之炊,要顯示這些窗體首先要製作這些窗體的預製體,然後載入。為此,我又設計了一個核心類PanelManager。

PanelManager主要負責窗體的建立和銷燬(隱藏),核心方法CreatePanel()。另外使用了物件池技術,快取窗體。

3.要動態載入窗體,必須獲得窗體資源的路徑,為此我設計了一個SysDefine類,此檔案用於定義一些預製體路徑常量,節點(Inspector面板中的物體位置)常量。(後期重構時打算用Json檔案配置)。載入資源的類ResourceManager。

4.此外,我還設計了一個幫助類Helper,目前實現的功能僅僅是自動化設定窗體節點的父節點。

下面,展示我今天下午的成果。

 1 using UnityEngine;
 2 
 3 public class BasePanel : MonoBehaviour
 4 {
 5     //窗體型別
 6    public EPanelType panelType;
 7     //是否是模態視窗
 8     public bool isModal;
 9     //是否是固定位置視窗
10     public bool isFixed;
11     //透明度
12     ETransparencyLevel transLevel;
13 
14 
15     //初始化
16     private
void Awake() 17 { 18 panelType = EPanelType.Normal; 19 isModal = true; 20 isFixed = false; 21 transLevel = ETransparencyLevel.Opaque; 22 } 23 24 private void Start() 25 { 26 //自動設定物體的父節點 27 Helper.GetInstance().SetParent(gameObject); 28 29 } 30 31 //開啟視窗 32 public void Open() 33 { 34 gameObject.SetActive(true); 35 } 36 //關閉視窗 37 public void Close() 38 { 39 gameObject.SetActive(false); 40 } 41 //凍結視窗 42 public void Freeze() 43 { 44 //TO DO 45 } 46 }
 1 using System.Collections.Generic;
 2 using UnityEngine;
 3 public class PanelManager
 4 {
 5     //本類例項
 6     private static PanelManager _instance;
 7     //儲存面板名字和對應的路徑字典
 8     public static Dictionary<string, string> dictPanelPath;
 9     //儲存已顯示的面板字典
10     public static Dictionary<string, BasePanel> dictCurPanel;
11     //儲存已隱藏的面板字典
12     public static Dictionary<string, BasePanel> dictHidePanel;
13     //儲存Popup型別面板的字典
14     public static Dictionary<string, Stack<BasePanel>> dictPopupPanel;
15 
16     //單例模式
17     private PanelManager() { }
18     public static PanelManager GetInstance()
19     {
20         if(_instance == null)
21         {
22             _instance = new PanelManager();
23 
24             InitProperties();
25         }
26         return _instance;
27     }
28     //初始化欄位
29     private static void InitProperties()
30     {
31         dictPanelPath = new Dictionary<string, string>();
32         dictCurPanel = new Dictionary<string, BasePanel>();
33         dictHidePanel = new Dictionary<string, BasePanel>();
34         dictPopupPanel = new Dictionary<string, Stack<BasePanel>>();
35     }
36     /// <summary>
37     /// 建立一個面板
38     /// 先檢查dictHidePanel集合裡是否存在此面板,有則取出顯示並加入dictCurPanel集合
39     /// 沒有,則建立一個,然後加如dictCurPanel集合。
40     /// </summary>
41     /// <param name="panelName">要建立的面板的名字</param>
42     /// <returns></returns>
43     public BasePanel CreatePanel(string panelName)
44     {
45         BasePanel basePanel = null;        
46         dictHidePanel.TryGetValue(panelName, out basePanel);
47         if(basePanel != null)
48         {
49             return basePanel;
50         }
51         else
52         {
53             //建立面板
54             GameObject go = ResourceManager.GetInstance().LoadAsset<GameObject>(panelName);
55             if(go != null)
56             {
57                 basePanel = go.GetComponent<BasePanel>();
58                 if(basePanel != null)
59                 {
60                     //新增到正在顯示的面板集合
61                     dictCurPanel.Add(panelName, basePanel);
62                 }
63                 else
64                 {
65                     Debug.LogError(GetType()+"你可能忘記掛在了BasePanel型別的指令碼");
66                 }
67                 return basePanel;
68             }
69             else
70             {
71                 Debug.Log(GetType()+"panelName可能不存在");
72 
73             }
74         }
75         return null;
76     }
77 
78 }
 1 using UnityEngine;
 2 
 3 public class ResourceManager
 4 {
 5     private static ResourceManager _instance;
 6     public static ResourceManager GetInstance()
 7     {
 8         if (_instance == null)
 9         {
10             _instance = new ResourceManager();
11         }
12         return _instance;
13     }
14     private ResourceManager() { }
15 
16     public T LoadAsset<T>(string path)where T:Object
17     {
18         Object o = Resources.Load(path);
19         //例項化
20         GameObject go = GameObject.Instantiate(o) as GameObject;
21       
22         return go as T;
23     }
24 
25 }
 1 public enum ETransparencyLevel
 2 {
 3     Opaque,                                 //不透明
 4     Translucence,                           //半透明的
 5     Transparent,                            //透明的
 6 }
 7 public enum EPanelType
 8 {
 9     Normal,
10     Popup,
11     HideOther
12 }
13 public  class PrefabPathStr
14 {
15     public const string uiRootPath = @"Prefabs/UIRoot";
16     public const string logOnPanelPath = @"Prefabs/LogOnPanel";
17 }
18 public class NodePathStr
19 {
20     public const string normalPath = @"UIRoot/Normal";
21     public const string popupPath = @"UIRoot/Popup";
22     public const string hiderOtherPath = @"UIRoot/HideOther";
23 }
24 
25 
26 
27 public class SysDefine
28 {
29 }
 1 using UnityEngine;
 2 
 3 public class Helper
 4 {
 5     private static Helper _instance = null;                                    //本類實;
 6     private static Transform normal;                                   //normal 節點
 7     private static Transform popup;                                    //popup 節點
 8     private static Transform hiderOther;                               //hiderOther 節點
 9     
10 
11     //單利模式
12     public static Helper GetInstance()
13     {
14         if(_instance == null)
15         {                                                               //本類例項化時,初始化節點欄位
16             normal = GameObject.Find(NodePathStr.normalPath).transform;
17             popup = GameObject.Find(NodePathStr.popupPath).transform;
18             hiderOther = GameObject.Find(NodePathStr.hiderOtherPath).transform;
19             _instance = new Helper();
20         }
21         return _instance;
22     }
23     private Helper() { }
24     /// <summary>
25     /// 若使用者自定義了parent則使用,若沒有則根據panelType自動設定。
26     /// </summary>
27     /// <param name="child">子物體</param>
28     /// <param name="parent">父物體</param>
29     public  void SetParent(GameObject child, Transform parent = null)
30     {
31         if(parent != null)
32         {
33             child.transform.SetParent(parent, true);
34             child.transform.localScale = new Vector3(1, 1, 1);
35             child.transform.localPosition = Vector3.zero;
36         }
37         else
38         {
39             if(child.GetComponent<BasePanel>()!= null)
40             {
41                 EPanelType panelType = child.GetComponent<BasePanel>().panelType;
42                 switch (panelType)
43                 {
44                     case EPanelType.Normal:
45                         child.transform.SetParent(normal);
46                         break;
47                     case EPanelType.Popup:
48                         child.transform.SetParent(popup);
49                         break;
50                     case EPanelType.HideOther:
51                         child.transform.SetParent(hiderOther);
52                         break;
53                     default:
54                         Debug.LogError("錯誤,未知的窗體型別");
55                         break;
56                 }
57                 child.transform.localScale = new Vector3(1, 1, 1);
58                 child.transform.localPosition = Vector3.zero;
59             }
60             else
61             {
62                 Debug.LogError(GetType()+ "請檢查此物體是否掛載了BasePanel型別指令碼!");
63             }
64            
65         }
66     }
67 }

啟動框架類StartGame.cs

 1 using UnityEngine;
 2 
 3 public class StartGame : MonoBehaviour
 4 {
 5   
 6     private GameObject uiRoot = null;
 7     void Start()
 8     {
 9         uiRoot = GameObject.FindGameObjectWithTag("UIRoot");
10         if (uiRoot != null)          //已生成UIRoot
11         {
12             Destroy(uiRoot);
13 
14         }
15         //獲取UIRoot物件
16         uiRoot = ResourceManager.GetInstance().LoadAsset<GameObject>(PrefabPathStr.uiRootPath);
17       
18         //修改克隆體的名字
19         uiRoot.name = "UIRoot";
20         //載入場景時不銷燬UIRoot
21         DontDestroyOnLoad(uiRoot);
22 
23         //載入登陸面板
24         PanelManager.GetInstance().CreatePanel(PrefabPathStr.logOnPanelPath);
25 
26     }
27 
28 }

測試程式碼LogOnPanel.cs

 1 using System.Collections;
 2 using System.Collections.Generic;
 3 using UnityEngine;
 4 
 5 public class LogOnPanel : BasePanel
 6 {
 7     private void Awake()
 8     {
 9         this.panelType = EPanelType.Normal;
10     }
11 
12 }

UIRoot預製體效果圖

LogOnPanel預製體效果圖:

執行效果圖: