版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_18192161/article/details/79241656
首先定义两个配置表:
UILevel.txt
层级ID 层级名称 层级起始深度 锁定层级(1,锁定层级,不会自动更新Panel深度) 层级描述
UILeveID UILevelName UILevelDepth UILevelLock UILevelDes
1 PanelPanel 0 0 常用面板,如主界面,匹配面板等等
2 TipsPanel 1000 0 tips面板
3 FixedPanel 1500 0 loading界面等等,金币等等
将UI分为3个层级,用于显示UI层次
UIConfig.txt 定义UI相关属性
UIID UI描述 UI类型 UI层级 UI是否会被销毁(0不会销毁,1会销毁) UI存在时间 UI路径 UI名称 UI锁定层级(1不会自动修改层级)
UIID UIDes UIType UILevel UICanDestroy UILife UIPath UIName UILockDepth
1001 登录UI Login 1 0 0 UI/Parfabs/ LoginPanel 0
1002 服务器选择UI Login 1 0 0 UI/Parfabs/ ServerPanel 0
1003 角色选择界面 Login 3 0 0 UI/Parfabs/ CreateRolePanel 0
1004 加载界面 Game 3 0 0 UI/Parfabs/ LoadingPanel 0
2001 游戏大厅 Game 1 0 0 UI/Parfabs/ MainPanel 0
2002 顶部信息面板 Game 3 0 0 UI/Parfabs/ TopPanel 0
2003 商城界面 Game 1 0 0 UI/Parfabs/ MallPanel 0
2004 背包面板 Game 1 1 10 UI/Parfabs/ BagPanel 0
2005 机械厂界面 Game 1 1 10 UI/Parfabs/ FactoryPanel 0
2006 剧情界面 Game 1 1 10 UI/Parfabs/ CheckPointPanel 0
2007 地图编辑界面 Game 1 1 10 UI/Parfabs/ EditorMapPanel 0
2008 战斗UI Game 1 1 10 UI/Parfabs/ FightPanel 0
2009 匹配模式选择界面 Game 1 1 10 UI/Parfabs/ MatchTypePanel 0
2010 匹配组选择界面 Game 1 1 10 UI/Parfabs/ MatchTypeGourpPanel 0
2011 组队界面 Game 1 1 10 UI/Parfabs/ TeamPanel 0
2012 匹配结果界面 Game 2 1 10 UI/Parfabs/ MatchResPanel 0
2013 英雄选择界面 Game 1 1 10 UI/Parfabs/ SelHeroPanel 0
2014 道具信息界面 Game 2 1 10 UI/Parfabs/ PropsInfoPanel 0
2015 战斗加载界面 Fight 1 1 10 UI/Parfabs/ FightLoadPanel 0
顶一个枚举类型,用来控制所有UIid
public enum UIType
{
/// <summary>
/// 登录注册面板
/// </summary>
LoginPanel = 1001,
/// <summary>
/// 服务器面板
/// </summary>
ServerPanel = 1002,
/// <summary>
/// 角色选择面板
/// </summary>
SelectRolePanel = 1003,
/// <summary>
/// 加载面板
/// </summary>
LoadingPanel = 1004,
/// <summary>
/// 游戏大厅
/// </summary>
MainPanel = 2001,
/// <summary>
/// 游戏模式面板
/// </summary>
TopPanel = 2002,
/// <summary>
/// 组队面板
/// </summary>
MallPanel = 2003,
/// <summary>
/// 背包面板
/// </summary>
BagPanel = 2004,
/// <summary>
/// 机械厂面板
/// </summary>
FactoryPanel = 2005,
/// <summary>
/// 剧情面板
/// </summary>
CheckPointPanel = 2006,
/// <summary>
/// 地图编辑面板
/// </summary>
EditorMapPanel = 2007,
/// <summary>
/// 战斗UI
/// </summary>
FightPanel = 2008,
/// <summary>
/// 匹配模式选择
/// </summary>
MatchTypePanel = 2009,
/// <summary>
/// 匹配模式组选择
/// </summary>
MatchTypeGroupPanel = 2010,
/// <summary>
/// 组队面板
/// </summary>
TeamPanel = 2011,
/// <summary>
/// 匹配结果面板
/// </summary>
MatchResPanel = 2012,
/// <summary>
/// 选择英雄面板
/// </summary>
SelHeroPanel = 2013,
/// <summary>
/// 道具信息面板
/// </summary>
PropsInfoPanel = 2014,
/// <summary>
/// 战斗服连接面板
/// </summary>
FightLoadPanel = 2015,
/// <summary>
/// 网络连接失败
/// </summary>
NetConnectFaildPanel = 5001,
}
抽象类 UIBase.cs 是所有UI的基类,所有UI类均需要继承此类
using UnityEngine;
using System.Collections;
public abstract class UIBase : MonoBehaviour {
/// <summary>
/// UIID
/// </summary>
public UIType UIType { get; set; }
/// <summary>
/// UI配置信息
/// </summary>
public UIConfig UIConfig { get; set; }
/// <summary>
///上一个UI数据
/// </summary>
private object[] PreUIData { get; set; }
/// <summary>
/// 上一个UI
/// </summary>
private UIBase PreUIBase { get; set; }
/// <summary>
/// 是否为打开状态
/// </summary>
public bool IsOpen { get; private set; }
/// <summary>
/// 上一次操作时间
/// </summary>
private System.DateTime OpenTime;
/// <summary>
/// 是否检测
/// </summary>
private bool isDetection = false;
/// <summary>
/// 打开UI
/// </summary>
/// <param name="data"></param>
public void OpenUI(UIBase preUI,params object[] data)
{
IsOpen = true;
this.gameObject.SetActive(true);
PreUIBase = preUI;
PreUIData = data;
OpenTime = System.DateTime.Now;
isDetection = false;
OnOpenAni();
}
/// <summary>
/// 打开UI动画
/// </summary>
/// <param name="data"></param>
public virtual void OnOpenAni(params object[] data)
{
OnEnter(data);
}
/// <summary>
/// 打开UI
/// </summary>
public void OpenUI()
{
this.gameObject.SetActive(true);
OpenTime = System.DateTime.Now;
isDetection = false;
OnEnter(PreUIData);
}
/// <summary>
/// 当更新
/// </summary>
/// <param name="data"></param>
public void OnUpdate(params object[] data)
{
UpdateUI(data);
}
protected virtual void UpdateUI(params object[] data) {}
/// <summary>
/// 关闭UI动画
/// </summary>
public virtual void OnCloseAni()
{
OnClose();
}
/// <summary>
/// 关闭UI
/// </summary>
protected void OnClose()
{
OnExit();
IsOpen = false;
isDetection = true;
this.gameObject.SetActive(false);
}
/// <summary>
/// 获取打开时间
/// </summary>
public System.DateTime GetOpenTime
{
get {
return OpenTime;
}
}
/// <summary>
/// 初始化UI
/// </summary>
/// <param name="data"></param>
public abstract void OnInit(params object[] data);
/// <summary>
/// 进入UI
/// </summary>
/// <param name="data"></param>
protected abstract void OnEnter(params object[] data);
/// <summary>
/// 退出UI
/// </summary>
protected abstract void OnExit();
/// <summary>
/// 关闭UI
/// </summary>
protected void Close()
{
UIManager.Instance.CloseUI(UIType);
}
/// <summary>
/// 打开上一层UI
/// </summary>
protected void OpenPreUI()
{
if(PreUIBase!=null)
UIManager.Instance.OpenPreUI(PreUIBase,PreUIData);
}
}
UIManager.cs 为UI管理类,包括打开UI,关闭UI等操作
using UnityEngine;
using System.Collections.Generic;
using System.Collections;
using System;
public enum UIFilter
{
All,
Open,
Close,
}
public class UIManager : MonoBehaviour {
private static UIManager _instance;
public static UIManager Instance
{
get {
return _instance;
}
}
/// <summary>
/// UI缓存
/// </summary>
private Dictionary<UIType, UIBase> uiCache = new Dictionary<UIType, UIBase>();
/// <summary>
/// 当前显示的主UI
/// </summary>
public UIBase CurUiBase { get;private set; }
/// <summary>
/// loading 界面
/// </summary>
public LoadingPanel LoadPanel { get; private set; }
/// <summary>
/// UI层级
/// </summary>
private Dictionary<int, Transform> uiLevel = new Dictionary<int, Transform>();
void Awake()
{
_instance = this;
}
void Start()
{
List<UILevel> levelInfo = UILevel.TryGet();
for (int i = 0; i < levelInfo.Count; i++)
{
Transform obj = CreateLevel(string.Format("{0} - {1} -{2}", levelInfo[i].UILevelID,levelInfo[i].UILevelName,levelInfo[i].UILevelDepth));
uiLevel.Add(levelInfo[i].UILevelID,obj);
}
StartCoroutine(DetectionUI());
if (LoadPanel == null)
{
LoadPanel = (LoadingPanel)GetUIBase(UIType.LoadingPanel);
LoadPanel.CloseLoading();
}
OpenUI( UIType.LoginPanel);
//OpenUI( UIType.MainPanel);
//OpenTips(UIType.TopPanel);
//MusicControl.Instance.PlayBackMusic("LoginAudio");
}
/// <summary>
/// UI销毁计时器
/// </summary>
/// <returns></returns>
IEnumerator DetectionUI()
{
yield return new WaitForSeconds(360);
if (uiCache.Count > 0)
{
List<UIBase> bases = new List<UIBase>(uiCache.Values);
for (int i = 0; i < bases.Count; i++)
{
if (!bases[i].UIConfig.UIisDestroy) continue;
System.TimeSpan ts = System.DateTime.Now - bases[i].GetOpenTime;
if (ts.TotalMinutes >= bases[i].UIConfig.UILife)
{
Destroy(bases[i].gameObject);
uiCache.Remove(bases[i].UIType);
}
}
}
}
/// <summary>
/// 清楚UI
/// </summary>
/// <param name="type"></param>
public void ClearScene(SceneType type)
{
List<UIBase> bases = new List<UIBase>(uiCache.Values);
for (int i = 0; i < bases.Count; i++)
{
if (bases[i].UIConfig.UIType.Equals(type.ToString()))
{
Destroy(bases[i].gameObject);
uiCache.Remove(bases[i].UIType);
}
}
}
/// <summary>
/// 打开UI
/// </summary>
/// <param name="uiType"></param>
/// <param name="data"></param>
public void OpenUI(UIType uiType,params object[] data)
{
if (uiCache.ContainsKey(uiType))
{
if(CurUiBase!=null)
CurUiBase.OnCloseAni();
uiCache[uiType].OpenUI(CurUiBase, data);
CurUiBase = uiCache[uiType];
return;
}
UIBase uiBase = GetUIBase(uiType);
if (uiBase == null) return;
if (CurUiBase != null)
CurUiBase.OnCloseAni();
uiBase.OnInit();
uiBase.OpenUI(CurUiBase, data);
CurUiBase = uiBase;
}
/// <summary>
/// 打开上一层UI
/// </summary>
/// <param name="uiBase"></param>
/// <param name="data"></param>
public void OpenPreUI(UIBase uiBase, params object[] data)
{
if (CurUiBase != null)
CurUiBase.OnCloseAni();
uiBase.OpenUI();
CurUiBase = uiBase;
}
/// <summary>
/// 打开tips
/// </summary>
/// <param name="uiType"></param>
/// <param name="data"></param>
public void OpenTips(UIType uiType, params object[] data)
{
if (uiCache.ContainsKey(uiType))
{
uiCache[uiType].OpenUI(CurUiBase, data);
return;
}
UIBase uiBase = GetUIBase(uiType);
if (uiBase == null) return;
uiBase.OnInit();
uiBase.OpenUI(CurUiBase, data);
}
/// <summary>
/// 更新UI
/// </summary>
/// <param name="uiType"></param>
/// <param name="data"></param>
public void UpdateUI(UIType uiType, params object[] data)
{
UIBase uiBase = GetUI(uiType);
if (uiBase != null)
uiBase.OnUpdate(data);
}
/// <summary>
/// 获取标签
/// </summary>
/// <param name="uiType"></param>
/// <returns></returns>
public UIBase GetUI(UIType uiType, UIFilter filter = UIFilter.Open)
{
switch (filter)
{
case UIFilter.Open:
if (uiCache.ContainsKey(uiType) && uiCache[uiType].IsOpen)
return uiCache[uiType];
break;
case UIFilter.Close:
if (uiCache.ContainsKey(uiType) && !uiCache[uiType].IsOpen)
return uiCache[uiType];
break;
case UIFilter.All:
if (uiCache.ContainsKey(uiType))
return uiCache[uiType];
break;
}
return null;
}
/// <summary>
/// 获取UI
/// </summary>
/// <param name="uiType"></param>
/// <returns></returns>
private UIBase GetUIBase(UIType uiType)
{
UIConfig config = UIConfig.TryGet(((int)uiType).ToString());
if (config == null)
{
Debug.Log(string.Format("获取ui:{0}-{1} 数据失败", uiType.ToString(), (int)uiType));
return null;
}
GameObject uiObj = GameObject.Instantiate(Resources.Load(config.UIPath + config.UIName)) as GameObject;
if (uiObj == null)
{
Debug.Log(string.Format("获取ui:{0}-{1} 模型失败", uiType.ToString(), (int)uiType));
return null;
}
uiObj.transform.parent = uiLevel[config.UILevel];
uiObj.transform.localPosition = Vector3.zero;
uiObj.transform.localScale = Vector3.one;
uiObj.transform.localEulerAngles = Vector3.zero;
//如果锁定UI层级
if(!config.UILockDepth)
ChangePanel(config.UILevel,uiObj.transform);
UIBase uiBase = uiObj.GetComponent<UIBase>();
uiBase.UIConfig = config;
uiBase.UIType = uiType;
uiCache.Add(uiType, uiBase);
return uiBase;
}
/// <summary>
/// 关闭UI
/// </summary>
/// <param name="uiType"></param>
public void CloseUI(UIType uiType)
{
if (uiCache.ContainsKey(uiType))
uiCache[uiType].OnCloseAni();
}
/// <summary>
/// 关闭所有UI
/// </summary>
public void CloseAll()
{
List<UIBase> bs = new List<UIBase>(uiCache.Values);
for (int i = 0; i < bs.Count; i++)
{
if (bs[i].IsOpen)
bs[i].OnCloseAni();
}
}
/// <summary>
/// 过滤关闭所有
/// </summary>
/// <param name="filter"></param>
public void CloseAll(UIType filter)
{
List<UIBase> bs = new List<UIBase>(uiCache.Values);
for (int i = 0; i < bs.Count; i++)
{
if (bs[i].IsOpen&&bs[i].UIType!=filter)
bs[i].OnCloseAni();
}
}
/// <summary>
/// 创建层级
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
private Transform CreateLevel(string name)
{
GameObject go = new GameObject(name);
go.transform.parent = this.transform;
go.transform.localPosition = Vector3.zero;
go.transform.localScale = Vector3.one;
go.transform.localEulerAngles = Vector3.zero;
return go.transform;
}
private void ChangePanel(int level,Transform obj)
{
//如果锁定层级深度则跳过
UILevel levelInfo = UILevel.TryGet(level.ToString());
if (levelInfo.UILevelLock) return;
int curMaxLevel = GetMax(levelInfo);
UIPanel[] panels = obj.GetComponentsInChildren<UIPanel>();
for (int i = 0; i < panels.Length; i++)
{
panels[i].depth = ++curMaxLevel;
}
}
/// <summary>
/// 获取当前面板最大层级
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
private int GetMax(UILevel level)
{
int maxDepth = level.UILevelDepth;
UIPanel[] panels = uiLevel[level.UILevelID].GetComponentsInChildren<UIPanel>();
for (int i = 0; i < panels.Length; i++)
{
if (panels[i].depth > maxDepth)
maxDepth = panels[i].depth;
}
return maxDepth;
}
}
打开一个UI
UIManager.Instance.OpenUI( UIType.LoginPanel);
运行后UI效果:
最终:
注意如果需要加入UI动画,需要在UI类中重写OnOpenAni()和OnCloseAni()方法,动画结束后不要忘了调用OnOpen()和OnClose()方法
有关配置表解析部分可以查看我的文章 “Unity3d txt配置表读取” 或 自行解析
http://blog.csdn.net/qq_18192161/article/details/79220695