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预制体效果图:

运行效果图:

 

posted @ 2018-12-29 18:53  _清风明月  阅读(392)  评论(0编辑  收藏  举报