赞
踩
含义:UI框架用于管理场景中所有的面板,负责控制面板之间的跳转
1、随着游戏系统的复杂化,UI控件越来越多,各个UI之间的直接通讯,已经UI与GameObject之间的关系会越来越复杂
2、代码耦合性会很强
MainMenuPanel:主菜单面板
BagPanel:背包面板
ItemMessagePanel:物品信息面板
ShopPanel:商城面板
SkillPanel:技能面板
SystemPanel:系统面板
TaskPanel:技能面板
我们将设计好的面板做成预制体,放在Resources的目录下。
UIPanelInfo.json
{ "infoList": [ { "panelTypeString": "ItemMessage", "path": "UIPanel/ItemMessagePanel" }, { "panelTypeString": "BagPanel", "path": "UIPanel/BagPanel" }, { "panelTypeString": "MainMenu", "path": "UIPanel/MainMenuPanel" }, { "panelTypeString": "Shop", "path": "UIPanel/ShopPanel" }, { "panelTypeString": "Skill", "path": "UIPanel/SkillPanel" }, { "panelTypeString": "System", "path": "UIPanel/SystemPanel" }, { "panelTypeString": "Task", "path": "UIPanel/TaskPanel" } ] } 将所有信息作为一个infolist类的对象
UIPanelType
public enum UIPanelType
{
BagPanel,
ItemMessage,
MainMenu,
Shop,
Skill,
System,
Task,
}
UIManager
public class UIManager { private Dictionary<UIPanelType, string> panelPathDicr;//存储所有面板Prefab的路径,UIPanelType类型,string用于存储路径 private UIManager() { ParseUIPanelTypeJson();//调用ParseUIPanelTypeJson方法解析Json文件 } //单例化 private static UIManager instance; public static UIManager GetInstance() { if (instance == null) { instance = new UIManager(); } return instance; } [Serializable] class UIPanelTypeJson//将Json文件视作一个整体,直接将其转换为List<UIPanelInfo> { public List<UIPanelInfo> infoList; } //解析Json文件 private void ParseUIPanelTypeJson() { panelPathDicr = new Dictionary<UIPanelType, string>();//生成一个字典 TextAsset ta = Resources.Load<TextAsset>("UIPanelType");//加载Json文件中的UIPanelType信息 UIPanelTypeJson jsonObject = JsonUtility.FromJson<UIPanelTypeJson>(ta.text);//JsonUtility——工具类,将Json中的文件解析为对象,ta.text就是JSON信息,将JSON信息转换为UIPanelTypeJson类 //总的意思就是将JSON文件转换为UIPanelTypeJson类,而UIPanelTypeJson类中则是List<UIPanelInfo>,并其字段infoList对应JSON文件的类名 foreach (UIPanelInfo info in jsonObject.infoList)//遍历UIPanelInfo的数组 { //Debug.Log(info.panelType); panelPathDicr.Add(info.panelType, info.path);//这里的info相对于生成一个jsonObject.infoList,因此info就是数组中的一个元素。 //将对象加入到字典当中去 } } public void Test()//测试 { string path; panelPathDicr.TryGetValue(UIPanelType.Shop, out path); Debug.Log(path); } }
UIPanelInfo
[Serializable] public class UIPanelInfo:ISerializationCallbackReceiver //将UIPanelInfo进行序列化,[Serializable]标签就是运行下面字段可进行读盘和写盘,负责与Json文件向对应,读取Json的文件,传递数据,可以避免直接修改Json文件 { [NonSerialized] public UIPanelType panelType;//记录Json文件中的panelType对象 //由于无法直接解析UIPanelType,所有使用string来接受Json数据 public string panelTypeString; //{第一种方式转换方式。 // get // { // return panelType.ToString(); // } // set // { // UIPanelType type = (UIPanelType)System.Enum.Parse(typeof(UIPanelType), value); // panelType = type; // } //} public string path;//记录path的路径字段 //反序列化 从文本信息到对象 public void OnAfterDeserialize()//每次反序列化后就会调用 { UIPanelType type = (UIPanelType)System.Enum.Parse(typeof(UIPanelType), panelTypeString); panelType = type;//将文本中的panelTypeString强制转换成UIPanelType } public void OnBeforeSerialize()//每次序列化之前调用这个方法 { } }
分析: 首先 1、UIPanelType类 作为一个枚举类,用于记录各个面板,保存面板的类型 2、UIPanelType.json 这是一个Json文件,用于存储各个面板的具体信息 例如: "panelTypeString": "MainMenu", "path": "UIPanel/MainMenuPanel" panelTypeString保存对象 path保存路径 3、UIPanelInfo 负责与Json文件向对应 public UIPanelType panelType;//记录Json文件中的panelType对象 public string path;//记录path的路径字段 这里要将其设置为可序列化的状态[Serializable],让这个类可以读盘与写盘,方便后期对信息进行修改 ,也可以避免直接修改Json文件 4、UIManger 是UI框架的核心,负责管理各种框架 第一步,将其设置为单例模式 第二步,将Json文件解析 第三步,使用UIPanelInfo的数组来接受Json文件的信息 第四步,遍历UIPanelInfo数组,并将其中的数据加入字典当中 其中有两个关键点。 第一,加载Json文件,并将文件解析为UIPanelInfo对象的数组 第二,遍历数组,并加入字典中,方便以后对其数据进行各种操作
BasePanel的设计
public class BasePanel : MonoBehaviour { /// <summary> /// 界面被显示出来 /// </summary> public virtual void OnEnter() { } /// <summary> /// 界面暂停 /// </summary> public virtual void OnPause() { } /// <summary> /// 界面继续 /// </summary> public virtual void OnResume() { } /// <summary> /// 界面不显示,退出这个界面,界面被关闭 /// </summary> public virtual void OnExit() { } }
BagPanel继承BasePanel
public class BagPanel:BasePanel { private CanvasGroup canvasGroup; private void Start() { if (canvasGroup == null) { canvasGroup = GetComponent<CanvasGroup>(); } } /// <summary> /// 处理页面的关闭 /// </summary> public override void OnExit() { // canvasGroup.alpha = 0; canvasGroup.blocksRaycasts = false; transform.DOLocalMoveX(600, 0.5f).OnComplete(() => canvasGroup.alpha = 0); } public void OnClosePanel() { UIManager.GetInstance().PopPanel(); } public override void OnEnter() { if (canvasGroup == null) { canvasGroup = GetComponent<CanvasGroup>(); } canvasGroup.alpha = 1; canvasGroup.blocksRaycasts = true; //弹出动画 Vector3 temp = transform.localPosition; temp.x = 600; transform.localPosition = temp; transform.DOLocalMoveX(0, 0.5f); } public override void OnPause() { canvasGroup.blocksRaycasts = false; } public override void OnResume() { canvasGroup.blocksRaycasts = true; } public void OnItemButtonClick() { UIManager.GetInstance().PushPanel(UIPanelType.ItemMessage); } }
完善后的UIManager
public class UIManager { private Transform canvasTransform; private Transform CanvasTransform { get { if (canvasTransform == null) { canvasTransform = GameObject.Find("Canvas").transform; } return canvasTransform; } } private Dictionary<UIPanelType, string> panelPathDicr;//存储所有面板Prefab的路径,UIPanelType类型,string用于存储路径 private Dictionary<UIPanelType, BasePanel> panelDict;//保存所有面板的游戏物体身上的BasePanel组件 private Stack<BasePanel> panelStacks; /// <summary> /// 把某个页面入栈,触发相应方法,并显示在界面上 /// </summary> public void PushPanel(UIPanelType panelType) { if (panelStacks == null) { panelStacks = new Stack<BasePanel>(); } //判断一下栈里面是否有页面 if (panelStacks.Count > 0) { BasePanel topPanel = panelStacks.Peek(); topPanel.OnPause(); } BasePanel panel = GetPanel(panelType); panel.OnEnter(); panelStacks.Push(panel); } /// <summary> /// 出栈,把页面从界面上移除 /// </summary> public void PopPanel() { if (panelStacks == null) { panelStacks = new Stack<BasePanel>(); } //BasePanel panel = GetPanel(panelType); if (panelStacks.Count <= 0) { return; } BasePanel topPanel = panelStacks.Pop(); topPanel.OnExit(); if (panelStacks.Count <= 0) return; BasePanel topPanel2 = panelStacks.Peek(); topPanel2.OnResume(); } /// <summary> /// 根据面板类型,得到实例化的面板 /// </summary> /// <returns></returns> public BasePanel GetPanel(UIPanelType panelType) { if (panelDict == null) { panelDict = new Dictionary<UIPanelType, BasePanel>(); } //BasePanel panel; //panelDict.TryGetValue(panelType, out panel);//TODO BasePanel panel = panelDict.TryGet(panelType); if (panel == null) { //如果找不到,就找这个面板的Prefab的路径,然后去根据Prefab去实例化面板 //string path; //panelPathDicr.TryGetValue(panelType, out path); string path = panelPathDicr.TryGet(panelType);//字典对象的值是已经决定了的,所以不需要使用泛型而dict对象就是panelPathDicr,不需要再赋值字典 var pan = Resources.Load(path); GameObject instPanel = GameObject.Instantiate(pan) as GameObject;//实例化 instPanel.transform.SetParent(CanvasTransform, false);//TODO false表示局部位置,而非全局位置 panelDict.Add(panelType, instPanel.GetComponent<BasePanel>()); return instPanel.GetComponent<BasePanel>(); } else { return panel; } } private UIManager() { ParseUIPanelTypeJson();//调用ParseUIPanelTypeJson方法解析Json文件 } //单例化 private static UIManager instance; public static UIManager GetInstance() { if (instance == null) { instance = new UIManager(); } return instance; } [Serializable] class UIPanelTypeJson//将Json文件视作一个整体,直接将其转换为List<UIPanelInfo> { public List<UIPanelInfo> infoList; } //解析Json文件 private void ParseUIPanelTypeJson() { panelPathDicr = new Dictionary<UIPanelType, string>();//生成一个字典 TextAsset ta = Resources.Load<TextAsset>("UIPanelType");//加载Json文件中的UIPanelType信息 UIPanelTypeJson jsonObject = JsonUtility.FromJson<UIPanelTypeJson>(ta.text);//JsonUtility——工具类,将Json中的文件解析为对象,ta.text就是JSON信息,将JSON信息转换为UIPanelTypeJson类 //总的意思就是将JSON文件转换为UIPanelTypeJson类,而UIPanelTypeJson类中则是List<UIPanelInfo>,并其字段infoList对应JSON文件的类名 foreach (UIPanelInfo info in jsonObject.infoList)//遍历UIPanelInfo的数组 { //Debug.Log(info.panelType); panelPathDicr.Add(info.panelType, info.path);//这里的info相对于生成一个jsonObject.infoList,因此info就是数组中的一个元素。 //将对象加入到字典当中去 } } public void Test()//测试 { string path; panelPathDicr.TryGetValue(UIPanelType.Shop, out path); Debug.Log(path); } }
分析
1、BasePanel作为基类被其他的具体类继承
而BasePanel中的方法为
OnEnter()——进入
OnPause()——暂停
OnResume()——恢复
OnExit()——退出
2、具体的类在继承的基础上,进行具体的修改,添加事件
3、UIManager则负责使用“栈”来对不同页面进行管理
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。