Unity3D基础UI框架

之前学了刘国柱老师的UI框架加上我自己的理解做了一个UI框架正好可以使用

这里附上刘国柱老师的博客 http://www.cnblogs.com/LiuGuozhu/ 受益颇深



基本UI框架的类图就是这样了

大体是根据MVC加上我的魔改而成的框架,至少我自己暂时觉得还是思路挺清晰的

Panel的切换是使用的Canvas Group的更改透明度,在加上使用


此方法来更改显示顺序和显隐的

其中的界面反向切换是使用的栈后入先出的特性

反向切换是指一个窗口弹出小窗口后,父窗口的Raycast需要取消,下面贴上核心代码

using System.Collections;
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class UIManager :MonoBehaviour {

    /// <summary>
    /// 单例模式:
    /// 1.定义一个静态的对象 在外界访问 内部构造
    /// 2.构造方法私有化
    /// </summary>
    #region 单例模式

    private static UIManager _instance;

    public static UIManager Instance
    {
        get
        {
            if (_instance == null)
            {
                UIManager[] instances = FindObjectsOfType<UIManager>();
                if (instances != null)
                {
                    _instance = instances[0];
                    for (var i = 1; i < instances.Length; i++)
                    {
                        Destroy(instances[i].gameObject);
                    }
                }
            }
            return _instance;
        }
    }

    #endregion


    private Transform _canvas;
    public Transform Canvas
    {
        get
        {
            if (_canvas == null)
                _canvas = GameObject.Find("Canvas").transform;
            return _canvas;
        }
    }
    //存储所有面板prefab的地址
    private Dictionary<UIPanelType, string> _DicPanelPath;
    //存储所有实例化的面板身上的BasePanel组件
    private Dictionary<UIPanelType, BasePanel> _DicPanel;
    //存储所有显示的面板上的BasePanel组件
    private Dictionary<UIPanelType, BasePanel> _DicShowPanel;
    //表示显示面板的栈
    private Stack<BasePanel> _StackPanel;
    //全屏显示的节点
    private Transform _TraFullScreen = null;
    //固定显示的节点
    private Transform _TraFixed = null;
    //弹出节点
    private Transform _TraPopUp = null;
    ////脚本节点
    //private Transform _TraScript = null;


    private void Awake()
    {
        ParseUIPanelPathJson();
        _StackPanel = new Stack<BasePanel>();
        _DicPanel = new Dictionary<UIPanelType, BasePanel>();
        _DicShowPanel = new Dictionary<UIPanelType, BasePanel>();
        _TraFullScreen = Canvas.Find("FullScreen");
        _TraFixed = Canvas.Find("Fixed");
        _TraPopUp = Canvas.Find("PopUp");
        DontDestroyOnLoad(Canvas.gameObject);
        //_TraScript = Canvas.Find("Script");
    }



    /// <summary>
    /// 把类型为反向切换的窗体入栈
    /// </summary>
    /// <param name="type"></param>
    private void PushPanel(UIPanelType type)
    {
        BasePanel basePanel = GetPanel(type);
        if (_StackPanel.Count >= 1)
        {
            BasePanel topPanel = _StackPanel.Peek();
            topPanel.OnPause();
        }
        _StackPanel.Push(basePanel);
        basePanel.OnEnter();
    }

    /// <summary>
    /// 把类型为反向切换的窗体出栈
    /// </summary>
    /// <param name="type"></param>
    private void PopPanel(UIPanelType type)
    {
        //如果栈里面为空,则返回
        if (_StackPanel.Count <= 0) return;
        BasePanel basePanel = GetPanel(type);
        BasePanel topPanel = _StackPanel.Peek();
        //如果当前要出栈的界面跟栈顶界面相同时 才会出栈
        if(basePanel.gameObject == topPanel.gameObject)
        {
            _StackPanel.Pop();
            topPanel.OnExit();
            //如果出栈后栈里面还有界面则恢复
            if(_StackPanel.Count >= 1)
            {
                _StackPanel.Peek().OnResume();
            }
        }
        else
        {
            Debug.LogError("栈顶界面不是此界面,请检查进出栈!!");
        }
        
    }

    /// <summary>
    /// 显示界面
    /// </summary>
    /// <param name="type"></param>
    public void ShowUIForms(UIPanelType type)
    {
        BasePanel basePanel = GetPanel(type);
        switch (basePanel.uiType.uiFormShowMode)
        {
            case UIFormShowMode.Normal:
                EnterUIFormsCache(type);
                break;
            //如果是反切换类型则入栈
            case UIFormShowMode.ReverseChange:
                PushPanel(type);
                break;
            //如果是隐藏其他的类型,清空显示的界面
            case UIFormShowMode.HideOther:
                HideOtherPanel(type);
                break;
        }
    }

    /// <summary>
    /// 隐藏界面 如果显示界面字典里面存在此界面
    /// </summary>
    /// <param name="type"></param>
    public void HideUIForms(UIPanelType type)
    {
        BasePanel basePanel = GetPanel(type);

        switch (basePanel.uiType.uiFormShowMode)
        {
            case UIFormShowMode.Normal:
                HideUIFormsCache(type);
                break;
            //如果是反切换类型则出栈
            case UIFormShowMode.ReverseChange:
                PopPanel(type);
                break;
            case UIFormShowMode.HideOther:
                HideUIFormsCache(type);
                break;
        }
    }

    /// <summary>
    /// 隐藏除此之外的Panel,如果不赋值则清空所有
    /// </summary>
    /// <param name="type"></param>
    public void HideOtherPanel(UIPanelType type = UIPanelType.Null)
    {
        foreach (KeyValuePair<UIPanelType,BasePanel> item in _DicShowPanel)
        {
            item.Value.OnExit();
        }
        _DicShowPanel.Clear();
        if (type != UIPanelType.Null)
        {
            BasePanel basePanel = GetPanel(type);
            basePanel.OnEnter();
            _DicShowPanel.Add(type, GetPanel(type));
        }
            
    }

    /// <summary>
    /// 将UI加入到已显示面板的字典中
    /// </summary>
    /// <param name="type"></param>
    private void EnterUIFormsCache(UIPanelType type)
    {
        //如果显示面板字典里面有当前面板则返回
        if (_DicShowPanel.ContainsKey(type)) return;
        BasePanel basePanel = GetPanel(type);
        _DicShowPanel.Add(type, basePanel);
        basePanel.OnEnter();
    }

    /// <summary>
    /// 将UI隐藏
    /// </summary>
    /// <param name="type"></param>
    private void HideUIFormsCache(UIPanelType type)
    {
        //如果显示面板字典里面没有当前面板则返回
        if (!_DicShowPanel.ContainsKey(type)) return;
        BasePanel basePanel = GetPanel(type);
        _DicShowPanel.Remove(type);
        basePanel.OnExit();
    }

    /// <summary>
    /// 根据面板类型得到实例化的面板
    /// </summary>
    /// <param name="type"></param>
    /// <returns></returns>
    private BasePanel GetPanel(UIPanelType type)
    {
        if (_DicPanel.ContainsKey(type))
        {
            return _DicPanel[type];
        }
        else
        {
            //如果找不到就找这个面板的prefab的路径,然后根据prefab去实例化面板
            BasePanel panel;
            string panelPath = _DicPanelPath.GetValue(type);
            GameObject insGo = GameObject.Instantiate(Resources.Load(panelPath),Canvas) as GameObject;
            insGo.name = type.ToString();
            panel = insGo.GetComponent<BasePanel>();
            switch (panel.uiType.uIFormParentType)
            {
                case UIFormParentType.FUllScreen:
                    insGo.transform.SetParent(_TraFullScreen);
                    break;
                case UIFormParentType.Fixed:
                    insGo.transform.SetParent(_TraFixed);
                    break;
                case UIFormParentType.PopUp:
                    insGo.transform.SetParent(_TraPopUp);
                    break;
            }
            _DicPanel.Add(type, panel);
            return panel;
        }
    }

    #region 解析地址json 并存储到字典中
    
    private void ParseUIPanelPathJson()
    {
        TextAsset text = Resources.Load<TextAsset>("UIPanelType");
        JSONObject jSONObject = new JSONObject(text.text);
        if (_DicPanelPath == null)
            _DicPanelPath = new Dictionary<UIPanelType, string>();
        foreach (JSONObject item in jSONObject.list)
        {
            string panelTypeString = item["panelTypeString"].str;
            string path = item["path"].str;
            UIPanelType uIPanelType = (UIPanelType)System.Enum.Parse(typeof(UIPanelType), panelTypeString);
            _DicPanelPath.Add(uIPanelType, path);
        }
    }

    #endregion

}
using System.Collections;
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;


public class BasePanel : MonoBehaviour {


    protected CanvasGroup cg;
    public UIType uiType;


    private void Awake()
    {
        InitData();
    }


    public virtual void OnCloseBtnClick()
    {
        UIManager.Instance.HideUIForms(uiType.uiPanelType);
    }


    public virtual void InitData()
    {
        if (cg == null)
            cg = this.gameObject.GetAndAddComponent<CanvasGroup>();
        if (uiType == null)
            uiType = new UIType();
    }




    /// <summary>
    /// 界面被显示出来
    /// </summary>
    public virtual void OnEnter()
    {
        cg.alpha = 1;
        cg.blocksRaycasts = true;
        this.gameObject.transform.SetAsLastSibling();
    }


    /// <summary>
    /// 界面暂停 指的是当其他界面在此界面之上,此界面不是主界面的时候,此界面不接受鼠标检测,如果不需要此功能可以适当更改
    /// </summary>
    public virtual void OnPause()
    {
        cg.blocksRaycasts = false;
    }


    /// <summary>
    /// 界面继续
    /// </summary>
    public virtual void OnResume()
    {
        cg.blocksRaycasts = true;
    }


    /// <summary>
    /// 界面不显示,退出这个界面
    /// </summary>
    public virtual void OnExit()
    {
        cg.alpha = 0;
        cg.blocksRaycasts = false;
    }
	
}

using System.Collections;
using System;
using System.Collections.Generic;
using UnityEngine;

public class UIType  {

    /// <summary>
    /// panel类别
    /// </summary>
    public UIPanelType uiPanelType;
    /// <summary>
    /// Panel的显示方式,有正常显示,隐藏其他和反向切换
    /// </summary>
    public UIFormShowMode uiFormShowMode = UIFormShowMode.Normal;
    /// <summary>
    /// 这个透明度暂时没用
    /// </summary>
    public UIFormLucencyType uIFormLucencyType = UIFormLucencyType.Lucency;
    /// <summary>
    /// Panel的父物体类型
    /// </summary>
    public UIFormParentType uIFormParentType = UIFormParentType.PopUp;

代码比较多,不过都有贴心的注释

猜你喜欢

转载自blog.csdn.net/qq_33413868/article/details/80771610