赞
踩
这套界面系统有面板基类(PanelBase)、面板管理器(PanelMgr)和多个具体的面板组成。所有面板都继承自PanelBase,而PanelMgr提供打开某个面板、关闭某个面板的方法。
先制作两个面板作为例子一个是开始界面(TitlePanel),另一个是游戏介绍(InfoPanel),如下图.


把这两个面板做成预设,放入Resources文件夹下。
PanelBase是一个面板基类,所有的面板逻辑都要继承它,一些设计要点如下。
1.面板的资源(如上面做成的两个面板预设)称为皮肤(skin,为GameObject类型),皮肤的路径称为skinPath。面板管理器会根据skinPath去实例化skin。
2.某些面板有层级关系,比如提示框总要覆盖普通面板。可定义PanelLayer类型的枚举,来指定面板的层级。
3.某些面板需要通过参数来确定他的表现形式。比如提示框,显示的内容由调用它的语句来指定。定义Object类型的变量args可用于接收PanelMgr传来的参数。
下图为面板的生命周期。

| 阶段 | 说明 |
|---|---|
| Init | Init是面板初始化阶段,用于处理args参数 |
| OnShowing | 面板显示前将会触发OnShowing,可用于处理面板中的监听事件 |
| OnShowed | 面板显示后将会触发OnShowed |
| Update | 每帧更新 |
| OnClosing | 关闭面板前调用OnClosing |
| OnClosed | 面板关闭后调用OnClosed |
代码(PanelBase)
using System.Collections; using System.Collections.Generic; using UnityEngine; public class PanelBase : MonoBehaviour { //皮肤路径 public string skinPath; //皮肤 public GameObject skin; //层级 public PanelLayer layer; //面板参数 public object[] args; #region 生命周期 //初始化 public virtual void Init(params object[] args) { this.args = args; } //开始面板前 public virtual void OnShowing() { } //显示面板后 public virtual void OnShowed() { } //帧更新 public virtual void Update() { } //关闭前 public virtual void OnClosing() { } //关闭后 public virtual void OnClosed() { } #endregion #region 操作 protected virtual void Close() { string name = this.GetType().ToString(); PanelMgr.instance.ClosePanel(name); } #endregion }
顾明思议,面板管理器的功能就是管理面板,他有一下三个功能。
1.层级管理
2.打开面板
3.关闭面板
在Unity中创建Canvas,并在画布上面添加名为Panel和Tips的两个空物体,有系统的所有面板都会放在这两个空物体下

代码
using System.Collections; using System.Collections.Generic; using UnityEngine; using System; public class PanelMgr : MonoBehaviour { public static PanelMgr instance; //画板 private GameObject canvas; //面板 用于存放已经打开的面板 public Dictionary<string, PanelBase> dict; //层级 存放各个层级所对应的父物体 private Dictionary<PanelLayer, Transform> layerDict; //开始 private void Awake() { instance = this; InitLayer(); dict = new Dictionary<string, PanelBase>(); } private void InitLayer() { canvas = GameObject.Find("Canvas"); if (canvas == null) Debug.LogError("panelMgr.InitLayerfail,Canvas is null"); //各个层级 layerDict = new Dictionary<PanelLayer, Transform>(); foreach(PanelLayer pl in Enum.GetValues(typeof(PanelLayer))) { string name = pl.ToString(); Transform transform = canvas.transform.Find(name); layerDict.Add(pl, transform); } } //打开面板 public void OpenPanel<T>(string skinpath,params object[] args) where T:PanelBase { //已经打开 string name = typeof(T).ToString(); if (dict.ContainsKey(name)) return; //面板脚本 PanelBase panel = canvas.AddComponent<T>(); panel.Init(args); dict.Add(name, panel); //加载皮肤 skinpath = (skinpath != "" ? skinpath : panel.skinPath); GameObject skin = Resources.Load<GameObject>(skinpath); if (skin == null) Debug.LogError("PanelMgr.OperPanelfail,skin is null,skinpath= " + skinpath); panel.skin = (GameObject)Instantiate(skin); //坐标 Transform skinTrans = panel.skin.transform; PanelLayer layer = panel.layer; Transform parent = layerDict[layer]; skinTrans.SetParent(parent, false); //panel的生命周期 panel.OnShowing(); panel.OnShowed(); } //关闭面板 public void ClosePanel(string name) { PanelBase panel = dict[name]; if (panel == null) return; panel.OnClosing(); dict.Remove(name); panel.OnClosed(); Destroy(panel.skin); Destroy(panel); } }
public enum PanelLayer
{
Panel,
Tips,
}
上面就是这个Ui系统的基本代码了
下面就拿上面创建好的两个面板为例子。
首先是创建好的TitlePanel面板
创建这样一个脚本
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class TitlePanel : PanelBase { private Button startBtn; private Button infoBtn; #region 生命周期 public override void Init(params object[] args) { base.Init(args); skinPath = "TitlePanel"; layer = PanelLayer.Panel; } public override void OnShowing() { base.OnShowing(); Transform skintrans = skin.transform; startBtn = skintrans.Find("btn_Start").GetComponent<Button>(); infoBtn = skintrans.Find("btn_Info").GetComponent<Button>(); startBtn.onClick.AddListener(OnStartClick); infoBtn.onClick.AddListener(OnInfoClick); } #endregion public void OnStartClick() { //开始游戏 //PanelMgr.instance.OpenPanel<OptionPanel>(""); } public void OnInfoClick() { PanelMgr.instance.OpenPanel<InfoPanel>(""); } }
不需要提前挂在物体上。
对于InfoPanel
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class InfoPanel : PanelBase { private Button closeBtn; #region 生命周期 public override void Init(params object[] args) { base.Init(args); skinPath = "InfoPanel"; layer = PanelLayer.Panel; } public override void OnShowing() { base.OnShowing(); Transform skintrans = skin.transform; closeBtn = skintrans.Find("btn_Close").GetComponent<Button>(); closeBtn.onClick.AddListener(OnCloseClick); } #endregion public void OnCloseClick() { Close(); } }
最后编写如下脚本调用TitlePanel就行
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Root : MonoBehaviour
{
private void Start()
{
PanelMgr.instance.OpenPanel<TitlePanel>("");
}
}在场景中创建一个名为Root的空物体挂在Root和PanelMgr

这样就完成了。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。