Unity3d 簡單實現 NGUI UI系統
阿新 • • 發佈:2018-11-27
首先定義兩個配置表:
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