U3D设计模式之UI框架
每个游戏的有UI,合理的UI管理可以更加节省游戏资源。本篇是对UI框架的总结。
UI框架就是把所有的UI做成Prefab存进Json文件中,等触发的时候再通过点击事件实例化出相应的UI预制体。这样做的好处是,游戏面板上什么都没有,用到什么就生成什么,为了避免重复生成,采用单例的方式来实现。
一、搭建UI界面。
二、写代码:
using System.Collections; using System.Collections.Generic; using UnityEngine; using System; //转化枚举信息给json解析提供值 [Serializable]//序列化信息(把对象转化为文本,转换为二进制) public class UIPanelInfo : ISerializationCallbackReceiver//序列化接口 { [NonSerialized] public UIPanelType type;//定义枚举 public string PanelTypeString; public string path;//json解析时要把该类信息都传递过去,所以path信息也要获取 public void OnAfterDeserialize()//反序列化之后执行的内容就是文本变对象 { UIPanelType typeinfo=(UIPanelType)Enum.Parse(typeof(UIPanelType),PanelTypeString); type = typeinfo; } public void OnBeforeSerialize() { } }
using System.Collections; using System.Collections.Generic; using UnityEngine; public class TaskPanel: BasePanel { private CanvasGroup cg; // Use this for initialization void Start () { if (cg == null) { cg = GetComponent<CanvasGroup>(); } cg = GetComponent<CanvasGroup>(); } //重写显示界面 public override void OnEnter() { if (cg==null) { cg = GetComponent<CanvasGroup>(); } cg.blocksRaycasts = true; cg.alpha = 1; } public void ClosePanel() { UIManager.Instance.PopPanel(); } public override void OnExit() { cg.blocksRaycasts = false; cg.alpha = 0; } } -------------------------------------------------------------------------------- using System.Collections; using System.Collections.Generic; using UnityEngine; 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() { } } -------------------------------------------------------------------------------- //定义一个栈(Stack) Stack<BasePanel> stack; /// <summary> /// 把某个界面进栈,用于显示当前的界面 /// </summary> public void PushPanel(UIPanelType panelType) { if (stack==null) { stack = new Stack<BasePanel>(); } if (stack.Count>0) { Debug.Log(1231456); BasePanel basePanel= stack.Peek();//检测里面最上面的界面,然后去暂停 basePanel.OnPause(); } Debug.Log(6666); BasePanel bp = GetPanel(panelType); bp.OnEnter(); stack.Push(bp); } /// <summary> /// 出栈就是把这个界面移除 /// </summary> public void PopPanel() { Debug.Log("看一看"); if (stack == null) { stack = new Stack<BasePanel>(); } if (stack.Count <= 0) return; //关闭栈顶的界面(peek的东西) BasePanel bp= stack.Pop();//出栈//关闭子界面(预示着原来的老界面要继续激活) bp.OnExit(); if (stack.Count <= 0) return; BasePanel basePanel= stack.Peek();//老界面(之前暂停的界面)拿出来激活 basePanel.OnResume();//可以继续交互了 } } -------------------------------------------------------------------------------- using System.Collections; using System.Collections.Generic; using UnityEngine; using System; public class MainmenuPanel : BasePanel { private CanvasGroup cg; void Start () { if (cg == null) { cg = GetComponent<CanvasGroup>(); } cg = GetComponent<CanvasGroup>(); } //告诉UImanger我想要哪个界面,你就给我生成或者直接拿给我 public void OnClickType(string type) { UIPanelType panelType= (UIPanelType)Enum.Parse(typeof(UIPanelType),type); UIManager.Instance.PushPanel(panelType); Debug.Log(type); } public override void OnPause() { if (cg == null) { cg = GetComponent<CanvasGroup>(); } cg.blocksRaycasts = false; Debug.Log(888); } public override void OnResume() { base.OnResume(); cg.blocksRaycasts = true; } } -------------------------------------------------------------------------------- using System.Collections; using System.Collections.Generic; using UnityEngine; public class KnapsackPanel : BasePanel { private CanvasGroup cg; // Use this for initialization void Start() { if (cg == null) { cg = GetComponent<CanvasGroup>(); } } //重写显示界面 public override void OnEnter() { if (cg == null) { cg = GetComponent<CanvasGroup>(); } cg.blocksRaycasts = true; cg.alpha = 1; } public override void OnPause() { Debug.Log("调用"); cg.blocksRaycasts = false; } public override void OnResume() { cg.blocksRaycasts = true; } public void ClosePanel() { UIManager.Instance.PopPanel(); } public override void OnExit() { cg.blocksRaycasts = false; cg.alpha = 0; } public void OnClickItem() { UIManager.Instance.PushPanel(UIPanelType.ItemMessage); } }
遇到的坑:
Json文件虽然可以读出来,但是无法在面板上显示,是因为Json文件里的变量名称要和代码里的变量名称一致,不然无法实别到。