《UI框架—基于Unity5.4UGUI(二)》
来源:互联网 发布:葫芦侠是什么软件 编辑:程序博客网 时间:2024/05/19 03:17
接着上一篇的介绍,这一篇就该干点实事了—上代码。但是在这之前,我先给出UI框架在Unity中的资源文件的截图,方便大家理解(其中的预制体和代码是根据上一篇博客的讲解给出):
1.存储面板类型和面板预设路径的Json文本如下:
{"infoList":[{"panelTypeString":"ItemMessage","path":"UIPanel/ItemMessagePanel"},{"panelTypeString":"Knapsack","path":"UIPanel/KnapsackPanel"},{"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"}]}
2.每个面板对应的枚举如下:
using UnityEngine;using System.Collections;public enum UIPanelType{ MainMenu, Knapsack, Shop, Skill, Task, System, ItemMessage}
3.每个UI界面信息对应的类(也就是解析出来的Json对应的类):
using UnityEngine;using System.Collections;using System;[Serializable]public class UIPanelInfo : ISerializationCallbackReceiver{//和json文件信息对应的一个类 //不可序列化的,因为这里unity解析json文件时没办法解析枚举类型,所以下面定义了一个string类型的字段panelTypeString,用于两者的转化 [NonSerialized] public UIPanelType panelType;//面板类型 public string panelTypeString; public string path;//面板所在路径 //实现ISerializationCallbackReceiver的接口, 反序列化方法,从文本信息到对象 public void OnAfterDeserialize() { UIPanelType type = (UIPanelType)System.Enum.Parse(typeof(UIPanelType), panelTypeString);//把一个字符串转化为一个枚举 panelType = type; } //实现接口, 序列化方法,从对象到文本信息 public void OnBeforeSerialize(){}}
4.(重点)UIManager管理各个UI面板的核心类:
using UnityEngine;using System.Collections;using System.Collections.Generic;/// <summary>/// 单例模式的核心:/// 1.只在该类内定义一个静态的对象,该对象在外界访问,在内部构造/// 2.构造函数私有化/// </summary>public class UIManager{//此类作为一个单例模式,即只有一个实例的模式 private static UIManager _instance; public static UIManager Instance { get { if (_instance == null) { _instance = new UIManager(); } return _instance; } } private UIManager() //构造函数私有化(单例模式) { ParseUIPanelTypeJson();//构造该类时会解析Json } private Dictionary<UIPanelType, string> panelPathDict;//存储所有Perfab面板的路径 private Dictionary<UIPanelType, BasePanel> panelDict;//借助BasePanel脚本保存所有实例化出来的面板物体(因为BasePanel脚本被所有面板预设物体的自己的脚本所继承,所以需要的时候可以根据BasePanel脚本来实例化每一个面板对象) private Stack<BasePanel> panelStack;//这是一个栈,用来保存实例化出来(显示出来)的面板 private Transform canvasTransform;//用来使实例化的面板归为它的子物体 private Transform CanvasTransform { get { if (canvasTransform == null) { canvasTransform = GameObject.Find("Canvas").transform; } return canvasTransform; } } //页面入栈,即把页面显示在界面上 public void PushPanel(UIPanelType panelType) { if (panelStack == null)//如果栈不存在,就实例化一个空栈 { panelStack = new Stack<BasePanel>(); } if (panelStack.Count > 0) { BasePanel topPanel = panelStack.Peek();//取出栈顶元素保存起来,但是不移除 topPanel.OnPause();//使该页面暂停,不可交互 } BasePanel panelTemp = GetPanel(panelType); panelTemp.OnEnter();//页面进入显示,可交互 panelStack.Push(panelTemp); } //页面出栈,即把页面从界面上移除 public void PopPanel() { if (panelStack == null) { panelStack = new Stack<BasePanel>(); } if (panelStack.Count <= 0) return; //关闭栈顶页面的显示 BasePanel topPanel1 = panelStack.Pop(); topPanel1.OnExit(); if (panelStack.Count <= 0) return; BasePanel topPanel2 = panelStack.Peek(); topPanel2.OnResume();//使第二个栈里的页面显示出来,并且可交互 } [System.Serializable] class UIPanelTypeJson //内部类里面就一个链表容器,用来配合解析 { public List<UIPanelInfo> infoList; } //根据面板类型UIPanelType得到实例化的面板 private BasePanel GetPanel(UIPanelType panelType) { if (panelDict == null)//如果panelDict字典为空,就实例化一个空字典 { panelDict = new Dictionary<UIPanelType, BasePanel>(); } //BasePanel panel; //panelDict.TryGetValue(panelType, out panel);//不为空就根据类型得到Basepanel BasePanel panel = panelDict.TayGet(panelType);//我们扩展的Dictionary的方法,代码作用同上两行 if (panel == null)//如果得到的panel为空,那就去panelPathDict字典里面根据路径path找到,然后加载,接着实例化 { string path = panelPathDict.TayGet(panelType);//我们扩展的Dictionary的方法 //panelPathDict.TryGetValue(panelType, out path); GameObject instPanel = GameObject.Instantiate(Resources.Load(path)) as GameObject;//根据路径加载并实例化面板 instPanel.transform.SetParent(this.CanvasTransform,false);//设置为Canvas的子物体,false表示实例化的子物体坐标以Canvas为准 //TODO panelDict.Add(panelType,instPanel.GetComponent<BasePanel>()); return instPanel.GetComponent<BasePanel>(); } else { return panel; } } //解析UIPanelType.json的信息 private void ParseUIPanelTypeJson() { panelPathDict = new Dictionary<UIPanelType, string>();//实例化一个字典对象 TextAsset ta = Resources.Load<TextAsset>("UIPanelType"); //获取UIPanelType.json文件的文本信息 UIPanelTypeJson jsonObject = JsonUtility.FromJson<UIPanelTypeJson>(ta.text);//把UIPanel.json文本信息转化为一个内部类的对象,对象里面的链表里面对应的是每个Json信息对应的类 foreach (UIPanelInfo info in jsonObject.infoList) { //Debug.Log(info.panelType); panelPathDict.Add(info.panelType, info.path);//把每一个进过json文件转化过来的类存入字典里面(键值对的形式) } }}
5.启动整个UI框架的类(这里只需要再启动游戏时加载主界面就好,其他界面是需要点击按钮时才会实例出来并显示):
using UnityEngine;using System.Collections;public class GameRoot : MonoBehaviour{ // Use this for initialization void Start () { UIManager.Instance.PushPanel(UIPanelType.MainMenu); }}
6.BasePanel各个面板的基类(定义各个面板共有的四个状态):
using UnityEngine;using System.Collections;//所有面板的公共基类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(){}}
7.主界面:
using UnityEngine;using System.Collections;public class MainMenuPanel : BasePanel{ private CanvasGroup canvasGroup;//获取CanvasGroup组件,用于控制该面板的交互功能 void Start() { canvasGroup = this.GetComponent<CanvasGroup>(); } public override void OnPause()//重写父类BasePanel的OnPause方法 { canvasGroup.blocksRaycasts = false;//使该面板失去交互功能 } //重写父类BasePanel的OnResume方法 public override void OnResume() { canvasGroup.blocksRaycasts = true;//使该面板继续交互功能 } //点击功能模块按钮加载面板,并将其入栈 public void OnPushPanel(string panelTypeString) { //把一个字符串转化为对应的枚举类型 UIPanelType panelType =(UIPanelType)System.Enum.Parse(typeof(UIPanelType), panelTypeString); UIManager.Instance.PushPanel(panelType); }}
8.任务面板:
using UnityEngine;using System.Collections;using DG.Tweening;public class TaskPanel : BasePanel { private CanvasGroup canvasGroup;//对该页面CanvasGroup组件的引用 void Start() { if(canvasGroup == null) canvasGroup = this.GetComponent<CanvasGroup>(); } //重写父类的OnEnter方法 public override void OnEnter() { if (canvasGroup == null) canvasGroup = this.GetComponent<CanvasGroup>(); this.canvasGroup.alpha = 0; this.canvasGroup.blocksRaycasts = true;//使该页面可交互 canvasGroup.DOFade(1, 0.6f);//使该页面渐渐显示,1是Alpha值 } //重写父类的OnExit方法 public override void OnExit() { this.canvasGroup.blocksRaycasts = false;//使该页面不可交互 canvasGroup.DOFade(0, 0.6f);//使该页面渐渐隐藏,0是Alpha值 } //点击关闭按钮事件 public void OnClose() { UIManager.Instance.PopPanel(); }}
9.背包面板:
using UnityEngine;using System.Collections;using DG.Tweening;public class KnapsackPanel : BasePanel { private CanvasGroup canvasGroup; void Awake() { this.canvasGroup = this.GetComponent<CanvasGroup>(); } public override void OnEnter() { this.canvasGroup.alpha = 1; this.canvasGroup.blocksRaycasts = true; Vector3 temp = this.transform.localPosition; temp.x = 600; this.transform.localPosition = temp; this.transform.DOLocalMoveX(0, 0.6f); } public override void OnExit() { //this.canvasGroup.alpha = 0; this.canvasGroup.blocksRaycasts = false; this.transform.DOLocalMoveX(-600, 0.6f).OnComplete(()=>canvasGroup.alpha =0); } public override void OnPause() { this.canvasGroup.blocksRaycasts = false; } public override void OnResume() { this.canvasGroup.blocksRaycasts = true; } //点击关闭按钮 public void OnClose() { UIManager.Instance.PopPanel(); } //点击装备,显示装备信息 public void OnItemButtonDown() { UIManager.Instance.PushPanel(UIPanelType.ItemMessage); }}
10.技能面板
using UnityEngine;using System.Collections;public class SkillPanel : BasePanel { private CanvasGroup canvasGroup; void Awake() { this.canvasGroup = this.GetComponent<CanvasGroup>(); } public override void OnEnter() { this.canvasGroup.alpha = 1; this.canvasGroup.blocksRaycasts = true; } public override void OnExit() { this.canvasGroup.alpha = 0; this.canvasGroup.blocksRaycasts = false; } public void OnClose() { UIManager.Instance.PopPanel(); }}
11.商城面板:
using UnityEngine;using System.Collections;public class ShopPanel : BasePanel { private CanvasGroup canvasGroup; void Awake() { this.canvasGroup = this.GetComponent<CanvasGroup>(); } public override void OnEnter() { this.canvasGroup.alpha = 1; this.canvasGroup.blocksRaycasts = true; } public override void OnExit() { this.canvasGroup.alpha = 0; this.canvasGroup.blocksRaycasts = false; } public void OnClose() { UIManager.Instance.PopPanel(); }}
12.系统设置面板:
using UnityEngine;using System.Collections;public class SystemPanel : BasePanel { private CanvasGroup canvasGroup; void Awake() { this.canvasGroup = this.GetComponent<CanvasGroup>(); } public override void OnEnter() { this.canvasGroup.alpha = 1; this.canvasGroup.blocksRaycasts = true; } public override void OnExit() { this.canvasGroup.alpha = 0; this.canvasGroup.blocksRaycasts = false; } public void OnClose() { UIManager.Instance.PopPanel(); }}
13.背包里的装备信息提示面板:
using UnityEngine;using System.Collections;using DG.Tweening;public class ItemMessagePanel : BasePanel{ private CanvasGroup canvasGroup; void Awake() { this.canvasGroup = this.GetComponent<CanvasGroup>(); } public override void OnEnter() { this.canvasGroup.alpha = 1; this.canvasGroup.blocksRaycasts = true; this.transform.localScale = Vector3.zero; transform.DOScale(1, 0.6f);//缩放动画,1代表结束时的缩放 } public override void OnExit() { //this.canvasGroup.alpha = 0; this.canvasGroup.blocksRaycasts = false; transform.DOScale(0, 0.6f).OnComplete(() => canvasGroup.alpha = 0); } public void OnClose() { UIManager.Instance.PopPanel(); }}
14.字典拓展类(用于拓展Dictionary类的TryGetValue( )方法,只是为了简化代码方便使用,UI框架里可有可无):
using UnityEngine;using System.Collections;using System.Collections.Generic;//对字典类的TayGetValue( )方法的扩展/// <summary>/// 尝试根据key得到value,得到返回value,否则返回null/// this Dictionary<Tkey,Tvalue> dict 这个字典表示我们要获取值value的字典/// 扩展方法规定类必须是一个静态类.里面包含的所有方法都必须是静态方法。扩展方法被定义为静态方法,但它们是通过实例方法语法进行调用的。 它们的第一个参数指定该方法作用于哪个类型,并且该参数以 this 修饰符为前缀。/// </summary>public static class DictionaryExtension { public static Tvalue TayGet<Tkey,Tvalue>( this Dictionary<Tkey,Tvalue> dict,Tkey key) { Tvalue value; dict.TryGetValue(key,out value); return value; }}
总结:该UI框架重点在于UI核心管理类(UIManager)的实现,其中使用栈先进后出,后进先出的思想实现了页面的逻辑管理。难点呢在于实现Json文本的解析。
阅读全文
5 0
- 《UI框架—基于Unity5.4UGUI(二)》
- 《UI框架—基于Unity5.4UGUI(一)》
- 基于UGUI 的 游戏UI框架的一些想法
- Unity-UGUI框架<二>
- unity5.4 UGUI 手机屏幕自适应分辨率
- Unity3D自学笔记——UGUI背包系统(二)UI设计实现及数据绑定
- 雨松MOMO UGUI 之 UI的深度学习(二)
- 【UGUI】Unity4.6 UI按钮绑定事件(二)
- (二十七)unity4.6学习Ugui中文文档-------Unity3D UI (uGUI)窗口扩展
- unity3d基于ugui的ui模块
- 基于Unity3D(UGUI)的背包系统<二>
- UGUI UI框架实现遇到的问题
- UI游戏框架(二)
- UGUI——拖动UI
- UGUI学习笔记4——UI Events,Event Triggers
- Unity +HTC VIVE 虚拟现实开发— UI设计(UGUI)
- 一个实用的android框架(二)—— UI
- VS2015 调试 UGUI (Unity5.5)
- (11)分苹果问题:将m个相同的苹果放到n个相同的盘子中,多少钟分法?
- python异常处理与网络链接
- 这是一个关于我的故事
- SDUT 1239 水仙花数
- ThreadLcoal
- 《UI框架—基于Unity5.4UGUI(二)》
- axios
- HDU2629 Identity Card【MAP+水题】
- hibernate的基础入门
- C++跨域重载实践
- Chrome浏览器flash player问题的终极解决方案
- 文章标题
- 关于两条绳子的问题
- 继承,对象间的类型转换,接口,多态的代码案例,以及对自身的反思