UGUI框架

本文介绍了UI框架的构建过程,包括创建UIPanelType表示面板类型,UIPanelInfo处理JSON数据,UIManager作为核心管理器,以及BasePanel和GameRoot类的使用,重点讲解了面板的跳转、存储和功能实现。
摘要由CSDN通过智能技术生成

1、什么是UI框架

主要功能:管理场景中所有的面板控制面板之间的跳转

2、简要描述UI框架的思路,步骤如下

 1、创建UIPanelType来表示UI面板的类型,保存现在这个工程所有的面板(比如此背包面板,商城面板,主菜单等)

2、创建UIPanelType.json保存所有panel和它对应的路径。所有的panel都存放在Resources文件夹中,以方便用到的时候加载,如图

json文件里面的UIPanle信息用一个数组保存(可以在浏览器搜过json在线校验就能校验格式是否正确)

3、创建UIPanelInfo类来实现程序于json的连接。用这个类来对应UIPanelJson,以此类来操作Json里面的数据

4、创建UIManager来管理所有的面板(UI框架的核心管理)实现的功能包括解析保存所有面板的信息(PanelPathDict)创建保存所有面板的实例(panelDict)管理保存所有显示的面板。除此之外,可以新增新功能

5、创建所面板的基类BasePanel来实现所有面板共同的功能的方法,比如界面开启,界面继续,界面关闭等(做成虚方法,让子类去实现)

6、创建GameRoot类来启动UI框,因为只用这个类挂载在游戏物体上面的(Canvas),所以只有这个类需要继承MonoBehaviour。

总结:

3、项目主要功能介绍 

1、简单说明:实现主菜单,背包界面,商城界面的跳转等

 2、具体功能实现

1、UIPanelType,用枚举类型来定义面板

2、 UI面板信息类UIPanelInfo

功能是:用来对应Json的文件信息

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

//用这个类来对应UIPanelJson,以此类来操作Json里面的数据
[Serializable]
public class UIPanelInfo : ISerializationCallbackReceiver   
{

    //与json里面名称对应起来
    [NonSerialized]
    public UIPanelType panelType;//Json无法解析这个类型的数据
    //将string类型的数据转化为上面枚举类型的数据
    public string panelTypeString;
/*    {
        get
        {
            //序列化
            return panelType.ToString();
        }
        set
        {
            Debug.Log(value);
            //反序列化
            UIPanelType type = (UIPanelType)System.Enum.Parse(typeof(UIPanelType), value);
            panelType = type;
        }
    }*/
    public string path;

    //反序列化  从文本信息 到对象
    public void OnAfterDeserialize()
    {
        UIPanelType type = (UIPanelType)System.Enum.Parse(typeof(UIPanelType), panelTypeString);
        panelType = type;
    }

    public void OnBeforeSerialize()
    {
        throw new NotImplementedException();
    }
}

3、 UIManager设置为单例模式

 (1)关于面板跳转的实现的说明:在游戏运行开始,实例化所需要的面板,用Stack来存储所有的实例化的面板,push代表实例化,pop代表关闭面板。

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

//UI框架的核心管理类
public class UIManager
{
    #region [UImanager单例的创建]
    private static UIManager _instance;

    /// <summary>
    /// 单例模式的核心
    ///1、定义一个静态的对象
    ///2、构造方法私有化
    /// </summary>
    //在外部就可以通过这个静态方法访问
    public static UIManager Instance
    {
        get
        {
            if (_instance == null)
            {
                _instance = new UIManager();
            }
            return _instance;
        }
    }

    //私有的让外接无法实例化本对象(构造方法)
    private UIManager()
    {
        //实例一创建就开始解析json文件
        ParseUIPanelTypeJson();
    }
    #endregion

    private Transform canvasTransform;//用来设置canvase和panel的父子关系
    private Transform CanvasTransform
    {
        get
        {
            if (canvasTransform == null)
            {
                canvasTransform = GameObject.Find("Canvas").transform;
            }
            return canvasTransform;
        }
    }
    private Dictionary<UIPanelType, string> panelPathDict;//存储所有的面板prafab的路径
    private Dictionary<UIPanelType, BasePanel> panelDict;//保存所有实例化面板的游戏物体身上的BasePanel组件
    private Stack<BasePanel> basePanelStack;

    #region 1、解析保存所有面板信息
    [Serializable]
    class UIPanelTypeJson
    {
        public List<UIPanelInfo> infoList;
    }
    //解析json文件
    private void ParseUIPanelTypeJson()
    {
        panelPathDict = new Dictionary<UIPanelType, string>();
        TextAsset ta = Resources.Load<TextAsset>("UIPanelType");

        //解析json文件(读取json里面的所有信息)
        // JsonUtility.FromJson可以生成一个对象
        UIPanelTypeJson jsonObject = JsonUtility.FromJson<UIPanelTypeJson>(ta.text);

        //通过jsonObject对象访问里面的数据即infoList
        foreach (UIPanelInfo info in jsonObject.infoList)
        {
            panelPathDict.Add(info.panelType, info.path);
        }
    }
    #endregion

    #region 2、创建保存所有面板实例
    /// <summary>
    /// 根据面板的类型,得到实例化的面板,再存到字典里面,下次就不用再多次实例化对象了
    /// </summary>
    /// <returns></returns>
    private BasePanel GetPanel(UIPanelType panelType)
    {
        if (panelDict == null)
        {
            panelDict = new Dictionary<UIPanelType, BasePanel>();
        }

        /*        BasePanel basePanel;
                panelDict.TryGetValue(panelType, out basePanel);//TODO*/

        BasePanel basePanel = panelDict.TryGet(panelType);

        //如果找不到,就找这个面板的prefab的路径,拿到这个路径创建它的实例
        if (basePanel == null)
        {
            //得到路径
            /*string path;
            panelPathDict.TryGetValue(panelType, out path);*/
            string path = panelPathDict.TryGet(panelType);
            //实例化加载的面板prefab
            GameObject instPanel = GameObject.Instantiate(Resources.Load(path)) as GameObject;
            //设置父物体
            instPanel.transform.SetParent(CanvasTransform, false);//false保持局部位置而不保持世界位置,要不然面板位置和scal将发生改变

            panelDict.Add(panelType, instPanel.GetComponent<BasePanel>());
            return instPanel.GetComponent<BasePanel>();
        }
        else
        {
            return basePanel;
        }


    }
    #endregion

    #region 3、管理保存所有显示页面的
    //把某个页面入栈,把某个页面显示在界面上
    public void PushPanel(UIPanelType panelType)
    {
        if (basePanelStack == null) basePanelStack = new Stack<BasePanel>();

        //判断一下stack里面是否有页面
        if(basePanelStack.Count > 0)
        {
            //取出栈顶的页面然后暂停它
            basePanelStack.Peek().OnPause();
        }
        //把新的界面开始并且入栈
        BasePanel basePanel = GetPanel(panelType);
        basePanel.OnEnter();
        basePanelStack.Push(basePanel);

    }

    //出栈,把页面从界面上移除
    public void PopPanel()
    {
        if (basePanelStack == null) basePanelStack = new Stack<BasePanel>();

        if (basePanelStack.Count <= 0) return;
        //关闭栈顶界面的显示
        basePanelStack.Pop().OnExit();
        //显示栈顶下面的界面
        if (basePanelStack.Count <= 0)
        {
            //没有界面了
            return;
        }

        //显示下一个界面
        basePanelStack.Peek().OnResume();

    }
    #endregion
    /// <summary>
    /// 方法test
    /// </summary>
    public void Test()
    {
        string path;
        panelPathDict.TryGetValue(UIPanelType.Knapsack, out path);
        Debug.Log(path);
    }
}

4、Basepanel

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class BasePanel : MonoBehaviour
{

    //界面开启
    public virtual void OnEnter()
    {

    }


    //界面暂停
    public virtual void OnPause()
    {


    }

    //界面继续
    public virtual void OnResume()
    {
        
    }

    //界面不显示,退出这个界面,界面被关闭
    public virtual void OnExit()
    {

    }
}

 5、以下就是各个功能面板的基本功能,此处介绍其一,其他的类似,并且之后可以在每个面板拓展新功能

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using DG.Tweening;

public class KnapsackPanel : BasePanel
{
    CanvasGroup canvasGroup;
    private void Awake()
    {
        canvasGroup = GetComponent<CanvasGroup>();
    }
    public void OnClosePanel()
    {
        UIManager.Instance.PopPanel();
    }

    public override void OnEnter()
    {
        canvasGroup.alpha = 1;
        canvasGroup.blocksRaycasts = true;
        //先设置背包面板在屏幕外面
        Vector3 temp = transform.localPosition;
        temp.x = 600;
        transform.localPosition = temp;
        //DoTween动画
        transform.DOLocalMoveX(0, 0.5f);
    }
    public override void OnExit()
    {
        //canvasGroup.alpha = 0;//隐藏
        canvasGroup.blocksRaycasts = false;//无法交互

        transform.DOLocalMoveX(600, .5f).OnComplete(() => canvasGroup.alpha = 0);
        
    }


    //处理Slot弹出ItemInfo
    public void OnItemButtonclick()
    {
        UIManager.Instance.PushPanel(UIPanelType.ItemMessage);
    }

    //打开ItemMessage时需要用到
    public override void OnPause()
    {
        canvasGroup.blocksRaycasts = false;//无法交互
    }

    //关闭ItemMessage时开启交互
    public override void OnResume()
    {
        canvasGroup.blocksRaycasts = true;
    }
}

 4、新知识的学习

 1、c#扩展类的应用,比如此项目里用到字典来存储面板及面板路径(PanelPathDict和panelDict)因为这个项目里面用了两个字典来存储面板信息,所以创建一个拓展方法来节省重复代码的使用。

功能就是根据传入的键来取得相应的值。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public static class DictionaryExtension //扩展字典类的方法
{
    /// <summary>
    /// 尝试根据key得到value,得到了就直接返回,没有得到直接返回null
    /// </summary>
    /// <typeparam name="Tkey">字典key的参数类型</typeparam>
    /// <typeparam name="Tvalue">字典值的参数类型</typeparam>
    /// <param name="dict">表示我们要获取值的字典</param>
    /// <param name=""></param>
    public static Tvalue TryGet<Tkey, Tvalue>(this Dictionary<Tkey, Tvalue> dict, Tkey key)
    {
        Tvalue value;
        dict.TryGetValue(key, out value);
        return value;
    }
}

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值