继续上篇内容哦!那么我们就先看Basepanel类,它是所有面板的父类,提供了一些共同的方法。
六大子类:那么我们就以任务面板模块为例子吧!进行讲解哦!下面的代码我们一字一句的看哦!看看到底是干啥的!后面我会带大家开发背包模块时再进行重点讲解背包模块的哦!它的功能要多一些的。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class TaskPanel : BasePanel
{
//任务面板上面的组件引用
private Button btnClose;
private CanvasGroup canvasGroup;
/// <summary>
/// 初始化方法
/// </summary>
void Awake()
{
RegisterComponent();
RegisterEvent();
}
void Start()
{
if (canvasGroup == null)
canvasGroup = GetComponent<CanvasGroup>();
}
/// <summary>
/// 复写父类的方法,在进入时要处理的事情
/// </summary>
public override void OnEnter()
{
if (canvasGroup == null)
canvasGroup = GetComponent<CanvasGroup>();
canvasGroup.alpha = 1;
canvasGroup.blocksRaycasts = true;
}
/// <summary>
/// 复写父类的方法,在退出时要处理的事情
/// </summary>
public override void OnExit()
{
canvasGroup.alpha = 0;
canvasGroup.blocksRaycasts = false;
}
/// <summary>
/// 查找组件方法
/// </summary>
public void RegisterComponent()
{
btnClose = transform.Find("btnClose").GetComponent<Button>();
}
/// <summary>
/// 注册侦听方法
/// </summary>
public void RegisterEvent()
{
btnClose.onClick.AddListener(delegate ()
{
UIManager.Instance.PopPanel();
});
}
}
这个只是任务面板的简单演示哦!看完了它们自己的类和父类,我们来看UIManager类吧!这个是核心类哦!要认真看哦!
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
/// <summary>
/// UI管理单例类(整个UI框架的核心管理类)
/// </summary>
public class UIManager
{
#region 单例模式
private static UIManager _instance;
public static UIManager Instance
{
get
{
if (_instance == null)
{
_instance = new UIManager();
}
return _instance;
}
}
#endregion
#region 所有的UI元素的父容器Canvas
/// <summary>
/// 字段,获取Canvas的位置
/// </summary>
private Transform canvasTransform;
/// <summary>
/// 属性,给字段提供一个可读的get属性
/// </summary>
private Transform CanvasTransform
{
get
{
if (canvasTransform == null)
{
canvasTransform = GameObject.Find("Canvas").transform;
}
return canvasTransform;
}
}
#endregion
/// <summary>
/// 字典 管理UIPanelprefab的路径< 枚举类型 字符串类型>
/// </summary>
private Dictionary<UIPanelType, string> panelPatDic; //存储所有面板prefab的路径
/// <summary>
/// 字典 管理每个UIPanel上面的BasePanel脚本
/// <枚举类型,保存是是游戏对象上的组件>
/// </summary>
private Dictionary<UIPanelType, BasePanel> panelDic;//存储所有实例化的面板(保存所有实例化面板的游戏物体身上的BasePanel组件)
/// <summary>
/// 栈 用来管理UIPanel面板的
/// 这里说一下为什么要用栈来管理UI面板哦!
/// 因为栈这种数据结构啊!具有先进后出,你想啊!我们最后打开的UI面板需要最先关闭的吧!
/// 所以我这里选用了栈这种数据结构
/// </summary>
private Stack<BasePanel> panelStack;
#region 构造函数
private UIManager()
{
ParseUIPanelTypeJosn();
}
#endregion
#region UI面板入栈操作
/// <summary>
/// 把某个页面入栈,把某个页面显示在界面上
/// </summary>
public void PushPanel(UIPanelType panelType)
{
if (panelStack == null)
panelStack = new Stack<BasePanel>();//初始化栈数据
//判断一下栈里面是否有界面
if (panelStack.Count > 0)
{
BasePanel topPanel = panelStack.Peek();
topPanel.OnPause();
}
BasePanel panel = GetPanel(panelType);
panel.OnEnter();
panelStack.Push(panel);
}
#endregion
#region UI面板出栈操作
/// <summary>
/// 出栈 把最上面的页面从界面移除
/// </summary>
public void PopPanel()
{
if (panelStack == null)
panelStack = new Stack<BasePanel>();
if (panelStack.Count <= 0)
return;
//关闭栈顶页面的显示
BasePanel topPanel = panelStack.Pop();
topPanel.OnExit();
if (panelStack.Count <= 0)
return;
//如果下面还有页面,就让下面的页面打开
BasePanel topPanel2 = panelStack.Peek();
topPanel2.OnResume();
}
#endregion
#region 返回BasePanel对象方法
/// <summary>
/// 根据面板类型得到实例化的面板上面的BasePanel
/// 核心哦!
/// </summary>
/// <param name="panelType"></param>
/// <returns></returns>
private BasePanel GetPanel(UIPanelType panelType)
{
if (panelDic == null)
{
panelDic = new Dictionary<UIPanelType, BasePanel>();//初始化字典
}
BasePanel panel;
panelDic.TryGetValue(panelType, out panel);
if (panel == null)
{
string path;
panelPatDic.TryGetValue(panelType, out path);
//Debug.Log(path);
GameObject instPanel = GameObject.Instantiate(Resources.Load(path)) as GameObject;
//如果为true,则相对于父级位置、缩放和旋转修改该对象,使得该对象保持与之前世界坐标空间一样的位置,旋转和缩放。
instPanel.transform.SetParent(CanvasTransform, false);
panelDic.Add(panelType, instPanel.GetComponent<BasePanel>());
return instPanel.GetComponent<BasePanel>();
}
else
{
return panel;
}
}
#endregion
[Serializable]//序列化
class UIPanelTypeJson
{
public List<UIPanelInfo> infoList;
}
/// <summary>
/// 解析我们的json文件 向字典中添加路径
/// </summary>
private void ParseUIPanelTypeJosn()
{
panelPatDic = new Dictionary<UIPanelType, string>();//存储所有面板prefab的路径的字典的初始化
TextAsset ta = Resources.Load<TextAsset>("UIType.json");
UIPanelTypeJson jsonObject = JsonUtility.FromJson<UIPanelTypeJson>(ta.text);//解析json文件的核心代码
foreach (UIPanelInfo info in jsonObject.infoList)
{
panelPatDic.Add(info.panelType, info.path);
}
}
}
上面的代码中会涉及到一个序列化和反序列的地方。这里我简单讲解一下,大家不懂的话,自己去百度一下即可哦!
/*
* 脚本名:UI面板信息类型管理
*
*/
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
//序列化
[Serializable]
public class UIPanelInfo : ISerializationCallbackReceiver
{
[NonSerialized]
public UIPanelType panelType;//这个字段不会进行序列化了[NonSerialized]
public string panelTypeString;
public string path;
/// <summary>
/// 反序列化:从文本信息到对象的过程
/// </summary>
public void OnAfterDeserialize()
{
//Enum.Parse 将一个或多个枚举常数的名称或数字值的字符串表示转换成等效的枚举对象。
UIPanelType type = (UIPanelType)System.Enum.Parse(typeof(UIPanelType), panelTypeString);
panelType = type;
}
public void OnBeforeSerialize()
{
}
}
本篇小结:本篇主要讲解了我们UI框架的核心管理类哦!一定要明白这个类是干嘛!不然后面无法进行开发的哦!