UI框架搭建DAY2
今天的主要任务是完善NormalPanel, 搭建PopupPanel。
在编写PanelManager的过程中,发现了一个bug。昨天把panelPath直接传给了ResourceManager.GetInstance().LoadAsset<GameObject>(path);
今天做了修改,并且添加了初始化dictPanelPath的方法,为此在SysDefine新添加了一个类,PanelNameStr。在Helper类里添加了以一个方法GetPathByName。
部分修改代码如下,偷了个懒,直接全部复制粘贴了:
PanelManager.cs
1 /* 2 2018.12.30修改记录:1.增加了SetDictPanelPath()方法 3 2.修改了CreatePanel()方法 4 3.增加了DestroyPanel()方法 5 */ 6 using System.Collections.Generic; 7 using UnityEngine; 8 public class PanelManager 9 { 10 //本类实例 11 private static PanelManager _instance; 12 //存储面板名字和对应的路径字典 13 public static Dictionary<string, string> dictPanelPath; 14 //存储已显示的面板字典 15 public static Dictionary<string, BasePanel> dictCurPanel; 16 //存储已隐藏的面板字典 17 public static Dictionary<string, BasePanel> dictHidePanel; 18 //存储Popup类型面板的字典 19 public static Dictionary<string, Stack<BasePanel>> dictPopupPanel; 20 21 //单例模式 22 private PanelManager() { } 23 public static PanelManager GetInstance() 24 { 25 if(_instance == null) 26 { 27 _instance = new PanelManager(); 28 29 InitProperties(); 30 SetDictPanelPath(); 31 } 32 return _instance; 33 } 34 //初始化字段 35 private static void InitProperties() 36 { 37 dictPanelPath = new Dictionary<string, string>(); 38 dictCurPanel = new Dictionary<string, BasePanel>(); 39 dictHidePanel = new Dictionary<string, BasePanel>(); 40 dictPopupPanel = new Dictionary<string, Stack<BasePanel>>(); 41 } 42 private static void SetDictPanelPath() 43 { 44 dictPanelPath.Add(PanelNameStr.LogOnPanel, PrefabPathStr.logOnPanelPath); 45 dictPanelPath.Add(PanelNameStr.RegisterPanel, PrefabPathStr.registerPanelPath); 46 } 47 /// <summary> 48 /// 创建一个面板 49 /// 先检查dictHidePanel集合里是否存在此面板,有则取出,显示,并加入dictCurPanel集合 50 /// 没有,则创建一个,然后加如dictCurPanel集合。 51 /// </summary> 52 /// <param name="panelName">要创建的面板的名字</param> 53 /// <returns></returns> 54 public BasePanel CreatePanel(string panelName) 55 { 56 BasePanel basePanel = null; 57 dictHidePanel.TryGetValue(panelName, out basePanel); 58 if(basePanel != null) 59 { 60 basePanel.Open(); 61 //添加到正在显示的面板集合 62 dictCurPanel.Add(panelName, basePanel); 63 return basePanel; 64 } 65 else 66 { 67 68 string path = Helper.GetInstance().GetPathByName(panelName); 69 70 //根据存储路径,加载预制体 71 GameObject go = ResourceManager.GetInstance().LoadAsset<GameObject>(path); 72 if(go != null) 73 { 74 basePanel = go.GetComponent<BasePanel>(); 75 if(basePanel != null) 76 { 77 //添加到正在显示的面板集合 78 dictCurPanel.Add(panelName, basePanel); 79 } 80 else 81 { 82 Debug.LogError(GetType()+"你可能忘记挂载了BasePanel类型的脚本"); 83 } 84 return basePanel; 85 } 86 else 87 { 88 Debug.Log(GetType()+"请检查配置文件,预制体不存在"); 89 90 } 91 } 92 return null; 93 } 94 95 /// <summary> 96 /// 1.从dictCurPanel集合中取出对应的面板 97 /// 2.隐藏 98 /// 3.加入dictHidePanel集合 99 /// </summary> 100 /// <param name="PanelName"></param> 101 public void DestroyPanel(string panelName) 102 { 103 BasePanel basePanel = null; 104 basePanel = dictCurPanel[panelName]; 105 if(basePanel == null) 106 { 107 Debug.LogError(GetType()+"面板不存在,请检查配置文件"); 108 return; 109 } 110 else 111 { 112 //关闭面板 113 basePanel.Close(); 114 //加入dictHidePanel集合 115 dictHidePanel.Add(panelName, basePanel); 116 } 117 } 118 119 }
为了测试DestroyPanel,新建了一个面板RegisterPanel。
在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 13 public void OnStartGameBtnClick() 14 { 15 //TO DO 16 } 17 //测试DestroyPanel()方法 18 public void OnRegisterBtnClick() 19 { 20 //隐藏自身 21 PanelManager.GetInstance().DestroyPanel(PanelNameStr.LogOnPanel); 22 //显示注册面板 23 PanelManager.GetInstance().CreatePanel(PanelNameStr.RegisterPanel); 24 } 25 26 }
另外在设计过程中和最初的想法有些出入,本来打算用工厂方法模式成产各种类型的Panel,现在类型已经在Awake方法里注册了,而且也不麻烦,所以把NormalPanel.cs,PopupPanel.cs,HideOtherPanel.cs删除了,我要去学习Shader了,下午继续更PopupPanel的搭建。
就在我光顾“五谷轮回之所”的时候想到我的代码还有一个严重的Bug,对象池技术中有生有死,有死有生,相互转化。而我的代码做了形式上的转化,却没有做内存处理。当从隐藏面板集合中取出一个面板显示的时候,就是由死转化到生,需要做两个处理,一是从dictHidePanel中移除这个键值对,而是向dictCurPanel中加入这个键值对。同理,当从当前显示面板中取出一个面板隐藏时,就是由生到死,也需要做对应的两个处理。修改代码如下:
1 //添加到正在显示的面板集合 2 dictCurPanel.Add(panelName, basePanel); 3 //从dictHidePanel集合中移除 4 dictHidePanel.Remove(panelName);
这是CreatePane()方法中修改的代码。
1 //从dictCurPanel集合中移除 2 dictCurPanel.Remove(panelName); 3 //加入dictHidePanel集合 4 dictHidePanel.Add(panelName, basePanel);
这是DestroyPanel()方法中修改的代码。