游戏UI框架——通过Json信息去加载UI面板
发布日期:2021-06-30 19:59:15 浏览次数:3 分类:技术文章

本文共 7734 字,大约阅读时间需要 25 分钟。

这种框架是通过加载编写好的面板Json信息的方式去实现的

例如如下图的游戏主界面中,当点击任务面板时其余的按钮都无法交互,当关闭了任务面板后其余的按钮恢复可交互行为


一:创建预制体

创建所需的所有面板,把他们都拖到Resources文件夹下成为预制体


二:创建存储不同面板信息的Json文件

[	{		"panelType": "Main",		"panelPath": "Prefabs/UI_Main"	},	{		"panelType": "Task",		"panelPath": "Prefabs/UI_Task"	},	{		"panelType": "Knapsack",		"panelPath": "Prefabs/UI_Knapsack"	},	{		"panelType": "Battle",		"panelPath": "Prefabs/UI_Battle"	},	{		"panelType": "Skill",		"panelPath": "Prefabs/UI_Skill"	},	{		"panelType": "Shop",		"panelPath": "Prefabs/UI_Shop"	},	{		"panelType": "Setting",		"panelPath": "Prefabs/UI_Setting"	},	{		"panelType": "ItemMessage",		"panelPath": "Prefabs/UI_ItemMessage"	}]

三:创建面板类型的枚举类

public enum PanelType{    Main,    Task,    Knapsack,    Battle,    Skill,    Shop,    Setting,    ItemMessage,}

四:编写UIManager管理类

——解析面板信息的Json文件,将面板类型和面板预制体路径存入一个字典里,字典的键是面板类型,值是面板预制体的路径

解析Json我这里使用了JSONObject插件

//存储每个UI信息的字典private Dictionary
uiInfoDict = new Dictionary
();///
/// 解析Json/// private void ParseJson(){ TextAsset ta = Resources.Load
("UIPanelInfo"); JSONObject j = new JSONObject(ta.text); foreach (var temp in j.list) { PanelType panelType = (PanelType)Enum.Parse(typeof(PanelType), temp["panelType"].str); string panelPath = temp["panelPath"].str; uiInfoDict.Add(panelType, panelPath); }}

——创建UIBase脚本,并提供虚方法重写

using UnityEngine;/// /// 每个UI面板的基类/// public class UIBase : MonoBehaviour{    ///     /// 面板显示时    ///     public virtual void OnView() { }    ///     /// 面板不显示时    ///     public virtual void OnDisview() { }    ///     /// 面板停止交互时    ///     public virtual void OnPause() { }    ///     /// 面板恢复交互时    ///     public virtual void OnResume() { }}

——得到面板物体上的UIBase组件并存入一个字典里(字典的键是面板类型,值是此面板身上的UIBase)
先从存储每个UI的字典uiDict中查找是否有当前类型面板的值,如果没有,则实例化面板并加到uiDict字典中

//存储每个UI的字典 private Dictionary
uiDict = new Dictionary
(); //存储每个UI信息的字典 private Dictionary
uiInfoDict = new Dictionary
(); ///
/// 得到面板(UIBase) /// ///
面板类型 ///
是否为一级界面 ///
此UI的根位置(在不是一级界面的情况下) ///
private UIBase GetPanel(PanelType panelType, bool isLevel1Panel = true, string uiRootPath = "") { UIBase uiPanel; uiDict.TryGetValue(panelType, out uiPanel); if (uiPanel != null) { return uiPanel; } else { string panelPath; uiInfoDict.TryGetValue(panelType, out panelPath); if (panelPath == null) { Debug.LogWarning("此面板类型的路径不存在"); return null; } else { GameObject panel = Resources.Load
(panelPath); panel = GameObject.Instantiate(panel); if (isLevel1Panel) { panel.transform.SetParent(UIRoot, false); } else { panel.transform.SetParent(GameObject.Find(uiRootPath).transform, false); } uiDict.Add(panelType, panel.GetComponent
()); return panel.GetComponent
(); } } }

——使用栈的数据结构去处理面板的显示
首先判断栈中是否存在面板,如果存在面板,则先让栈顶面板禁用交互,然后再得到当前类型的面板入栈并调用面板的显示方法

/// /// 显示面板/// /// 面板类型public void OpenUI(PanelType panelType){    if (panelStack.Count > 0)    {        UIBase topPanel = panelStack.Peek();        topPanel.OnUnInteractable();    }    UIBase uiPanel = GetPanel(panelType);    if (uiPanel == null)    {        return;    }    uiPanel.OnView();    panelStack.Push(uiPanel);}

——使用栈的数据结构去处理面板的关闭
首先将栈顶面板出栈并调用面板隐藏方法,如果栈中仍存在元素,则让当前栈顶元素启用交互

///  /// 关闭面板 ///  /// 是否销毁 public void CloseUI(bool destroy = false) {     if (panelStack.Count == 0)     {         return;     }     UIBase topPanel = panelStack.Pop();     topPanel.OnDisview();     if (destroy)     {         GameObject.Destroy(topPanel.gameObject     }     if (panelStack.Count > 0)     {         panelStack.Peek().OnInteractable();     } }

——在不同的面板脚本中重写四种状态

using UnityEngine;using UnityEngine.UI;public class UI_TaskPanel : UIBase{    public override void OnView()    {        gameObject.SetActive(true);    }    public override void OnDisview()    {        gameObject.SetActive(false);    }    public override void OnInteractable()    {        GetComponent
().blocksRaycasts = true; } public override void OnUnInteractable() { GetComponent
().blocksRaycasts = false; } public void OnCloseButtonDown() { UIManager.Instance.CloseUI(); }}

——————————UIManage的完整代码

using UnityEngine;using System.Collections.Generic;using System;/// /// 每个UI面板的基类/// public class UIBase : MonoBehaviour{    ///     /// 面板显示时    ///     public virtual void OnView() { }    ///     /// 面板不显示时    ///     public virtual void OnDisview() { }    ///     /// 面板不可交互时    ///     public virtual void OnUnInteractable() { }    ///     /// 面板可以交互时    ///     public virtual void OnInteractable() { }}public class UIManager{    //单例模式    private static UIManager _instance;    public static UIManager Instance    {        get        {            if (_instance == null)            {                _instance = new UIManager();            }            return _instance;        }    }    //UI的根位置    private Transform uiRoot;    private Transform UIRoot    {        get        {            if (uiRoot == null)            {                uiRoot = GameObject.Find("UICanvas").transform;            }            return uiRoot;        }    }    //存储每个UI的字典    private Dictionary
uiDict = new Dictionary
(); //存储每个UI信息的字典 private Dictionary
uiInfoDict = new Dictionary
(); //存储每个面板的栈 private Stack
panelStack = new Stack
(); private UIManager() { ParseJson(); } ///
/// 显示面板 /// ///
面板类型 public void OpenUI(PanelType panelType) { if (panelStack.Count > 0) { UIBase topPanel = panelStack.Peek(); topPanel.OnUnInteractable(); } UIBase uiPanel = GetPanel(panelType); if (uiPanel == null) { return; } uiPanel.OnView(); panelStack.Push(uiPanel); } ///
/// 显示面板 /// ///
面板类型 public void OpenUI(PanelType panelType, string uiRootName) { if (panelStack.Count > 0) { UIBase topPanel = panelStack.Peek(); topPanel.OnUnInteractable(); } UIBase uiPanel = GetPanel(panelType, false, uiRootName); if (uiPanel == null) { return; } uiPanel.OnView(); panelStack.Push(uiPanel); } ///
/// 关闭面板 /// ///
是否销毁 public void CloseUI(bool destroy = false) { if (panelStack.Count == 0) { return; } UIBase topPanel = panelStack.Pop(); topPanel.OnDisview(); if (destroy) { GameObject.Destroy(topPanel.gameObject); } Debug.Log(panelStack.Count); if (panelStack.Count > 0) { panelStack.Peek().OnInteractable(); } } ///
/// 解析Json /// private void ParseJson() { TextAsset ta = Resources.Load
("UIPanelInfo"); JSONObject j = new JSONObject(ta.text); foreach (var temp in j.list) { PanelType panelType = (PanelType)Enum.Parse(typeof(PanelType), temp["panelType"].str); string panelPath = temp["panelPath"].str; uiInfoDict.Add(panelType, panelPath); } } ///
/// 得到面板(UIBase) /// ///
面板类型 ///
是否为一级界面 ///
此UI的根位置(在不是一级界面的情况下) ///
private UIBase GetPanel(PanelType panelType, bool isLevel1Panel = true, string uiRootName = "") { UIBase uiPanel; uiDict.TryGetValue(panelType, out uiPanel); if (uiPanel != null) { return uiPanel; } else { string panelPath; uiInfoDict.TryGetValue(panelType, out panelPath); if (panelPath == null) { Debug.LogWarning("不存在当前面板类型的预制体"); return null; } else { GameObject panel = Resources.Load
(panelPath); panel = GameObject.Instantiate(panel); if (isLevel1Panel) { panel.transform.SetParent(UIRoot, false); } else { panel.transform.SetParent(GameObject.Find(uiRootName).transform, false); } uiDict.Add(panelType, panel.GetComponent
()); return panel.GetComponent
(); } } }}

转载地址:https://liuhaowen.blog.csdn.net/article/details/89460570 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:Unity中使用ViedoPlayer操作视频文件
下一篇:Unity自带Json解析库——JsonUtility

发表评论

最新留言

逛到本站,mark一下
[***.202.152.39]2024年04月19日 14时44分53秒