Unity3d 简单实现 NGUI UI系统

版权声明:本文为博主原创文章,未经博主允许不得转载。 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

猜你喜欢

转载自blog.csdn.net/qq_18192161/article/details/79241656
今日推荐