Unity3d游戏开发框架-UI管理类 UIManager

发表于2018-09-12
评论0 5.4k浏览
前面已经给大家介绍了Unity3d游戏开发框架中消息机制的使用,本篇继续介绍Unity3D游戏开发框架系列,掌握UI管理类UIManager的使用。

新建一个文件夹:UIMgr
新建2个C#脚本:BaseUI.cs UIMgr.cs
里面的UIMgr.cs继承了EventNode。EventNode在前面有讲,这里重新给出一下。
IResLoadListener.cs接口,资源加载回调
using UnityEngine;
using System.Collections;
public class BaseUI : MonoBehaviour 
{
    /// <summary>
    /// 当前界面名称
    /// </summary>
    [HideInInspector]
    public string UIName;
    private Transform mTransform;
    public Transform CacheTransform
    {
        get
        {
            if (mTransform == null) mTransform = this.transform;
            return mTransform;
        }
    }
    private GameObject mGo;
    public GameObject CacheGameObject
    {
        get
        {
            if (mGo == null) mGo = this.gameObject;
            return mGo;
        }
    }
    /// <summary>
    /// 显示当前UI
    /// </summary>
    /// <param name="param">附加参数</param>
    public void Show(object param = null)
    {
        CacheGameObject.SetActive(true);
    }
    /// <summary>
    /// 隐藏当前界面
    /// </summary>
    public void Hide()
    {
        CacheGameObject.SetActive(false);
    }
    /// <summary>
    /// 绑定脚本并且激活游戏物体会调用的方法
    /// </summary>
    void Awake() 
    {
        OnAwake();
    }
    /// <summary>
    /// 初始化UI主要用于寻找组件等
    /// </summary>
    public void UIInit()
    {
        OnInit();
    }
    /// <summary>
    /// 显示当前界面
    /// </summary>
    /// <param name="param">附加参数</param>
    protected virtual void OnShow(object param){ }
    /// <summary>
    /// 隐藏当前界面
    /// </summary>
    protected virtual void OnHide() { }
    /// <summary>
    /// 初始化当前界面
    /// </summary>
    protected virtual void OnInit() { }
    protected virtual void OnAwake() { }
    /// <summary>
    /// 删除当前UI 
    /// </summary>
    protected virtual void OnDestroy() { }
}

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class EventNode : MonoBehaviour
{
    /// <summary>
    /// 节点优先级
    /// </summary>
    public int EventNodePriority { set; get; }
    /// <summary>
    /// 所有消息集合
    /// </summary>
    private Dictionary<int, List<IEventListener>> mListeners = new Dictionary<int, List<IEventListener>>();
    /// <summary>
    /// 消息节点
    /// </summary>
    private List<EventNode> mNodeList = new List<EventNode>();
    /// <summary>
    /// 挂载一个消息节点到当前节点上
    /// </summary>
    /// <param name="node">消息节点</param>
    /// <returns>如果当前节点里面已经包含要添加的这个节点那么返回false</returns>
    public bool AttachEventNode(EventNode node)
    {
        if (node == null)
        {
            return false;
        }
        if (mNodeList.Contains(node))
        {
            return false;
        }
        int pos = 0;
        for (int i = 0; i < mNodeList.Count;i++ )
        {
            if (node.EventNodePriority > mNodeList[i].EventNodePriority)
            {
                break;
            }
            pos++;
        }
        mNodeList.Insert(pos,node);
        return true;
    }
    /// <summary>
    /// 卸载一个消息节点
    /// </summary>
    /// <param name="node">消息节点</param>
    /// <returns>如果节点不存在那么返回false</returns>
    public bool DetachEventNode(EventNode node)
    {
        if (!mNodeList.Contains(node))
        {
            return false;
        }
        mNodeList.Remove(node);
        return true;
    }
    /// <summary>
    /// 挂载一个消息监听器到当前的消息节点
    /// </summary>
    /// <param name="key">消息ID</param>
    /// <param name="listener">消息监听器</param>
    /// <returns>当前消息节点已经挂载了这个消息监听器那么返回false</returns>
    public bool AttachEventListener(int key,IEventListener listener)
    {
        if (listener == null)
        {
            return false;
        }
        if (!mListeners.ContainsKey(key))
        {
            mListeners.Add(key,new List<IEventListener>() { listener });
            return true;
        }
        if (mListeners[key].Contains(listener))
        {
            return false;
        }
        int pos = 0;
        for (int i = 0;i< mListeners[key].Count;i++ )
        {
            if (listener.EventPriority() > mListeners[key][i].EventPriority())
            {
                break;
            }
            pos++;
        }
        mListeners[key].Insert(pos,listener);
        return true;
    }
    /// <summary>
    /// 卸载一个消息节点
    /// </summary>
    /// <returns>如果当前消息节点不存在那么返回false</returns>
    public bool DetachEventListener(int key,IEventListener listener)
    {
       if (mListeners.ContainsKey(key) && mListeners[key].Contains(listener))
       {
           mListeners[key].Remove(listener);
           return true;
       }
       return false;
    }
    public void SendEvent(int key,object param1 = null,object param2 = null)
    {
        DispatchEvent(key, param1, param2);
    }
    /// <summary>
    /// 派发消息到子消息节点以及自己节点下的监听器上
    /// </summary>
    /// <param name="key">消息ID</param>
    /// <param name="param1"></param>
    /// <param name="param2"></param>
    /// <returns>如果中断消息返回true</returns>
    private bool DispatchEvent(int key,object param1,object param2)
    {
        for (int i = 0; i < mNodeList.Count;i++ )
        {
            if (mNodeList[i].DispatchEvent(key, param1, param2)) return true;
        }
        return TriggerEvent(key, param1, param2);
    }
    /// <summary>
    /// 消息触发
    /// </summary>
    /// <param name="key">消息id</param>
    /// <param name="param1"></param>
    /// <param name="param2"></param>
    /// <returns>是否中断</returns>
    private bool TriggerEvent(int key,object param1,object param2)
    {
        if (!this.gameObject.activeSelf || !this.gameObject.activeInHierarchy || !this.enabled)
        {
            return false;
        }
        if (!mListeners.ContainsKey(key))
        {
            return false;
        }
        List<IEventListener> listeners = mListeners[key];
        for (int i = 0; i < listeners.Count; i++)
        {
            if (listeners[i].HandleEvent(key, param1, param2)) return true;
        }
        return false;
    }
   void OnApplicationQuit()
    {
        mListeners.Clear();
        mNodeList.Clear();
    }
}

新建接口IResLoadListener.cs
using UnityEngine;
using System.Collections;
/// <summary>
/// 资源加载回调
/// </summary>
public interface IResLoadListener  
{
    void Finish(object asset);
    void Failure();
}

新建一个类UIMgr.cs继承EventNode
using UnityEngine;
using System.Collections;
using System;
using System.Collections.Generic;
public class UIMgr : EventNode 
{
    private static UIMgr mInstance;
    public static UIMgr Instance
    {
        get
        {
            return mInstance;
        }
    }
    /// <summary>
    /// 所有UI
    /// </summary>
    private Dictionary<string, BaseUI> mDicUI = new Dictionary<string, BaseUI>();
    /// <summary>
    /// 添加一个UI
    /// </summary>
    /// <param name="ui"></param>
    public void AddUI(BaseUI ui)
    {
        if (ui != null)
        {
            mDicUI[ui.UIName] = ui;
        }
    }
    /// <summary>
    /// 移除一个UI
    /// </summary>
    /// <param name="ui"></param>
    public void RemoveUI(BaseUI ui)
    {
        if (ui != null && mDicUI.ContainsKey(ui.UIName))
        {
            mDicUI.Remove(ui.UIName);
        }
    }
    /// <summary>
    /// 所有命令集合
    /// </summary>
    public List<Command> cmdList = new List<Command>();
    internal Transform UIROOT = null;
    void Awake() 
    {
        UIROOT = this.transform.FindChild("UIRoot");
        mInstance = this;
        DontDestroyOnLoad(this.gameObject);
    }
    #region 创建UI
    /// <summary>
    /// 创建UI
    /// </summary>
    /// <param name="uiName">UI名称</param>
    /// <param name="type">要绑定的脚本</param>
    /// <param name="listener">创建完成的回调</param>
    public void CreateUI(string uiName, Type type, ILoadUIListener listener)
    {
        cmdList.Add(Command.CreateCmd(type,uiName,listener));
    }
    /// <summary>
    /// 创建UI的实体部分
    /// </summary>
    /// <param name="cmd">命令</param>
    private void _Create(Command cmd)
    {
        BaseUI ui= null;
        mDicUI.TryGetValue(cmd.uiName, out ui);
        if (ui != null)
        {
            if (cmd.listener != null) cmd.listener.FiniSh(ui);
        }
        else
        {
            ResMgr.Instance.Load(cmd.uiName,new LoadResFinish(cmd));
        }
    }
    #endregion
    #region 显示UI
    /// <summary>
    /// 显示一个UI界面  如果不存在就创建
    /// </summary>
    /// <param name="uiName">ui名称</param>
    /// <param name="type">要绑定的脚本</param>
    /// <param name="listener">如果界面不存在则会有界面加载完成后的回调</param>
    /// <param name="param">要传入的参数</param>
    public void ShowUI(string uiName, Type type, ILoadUIListener listener,object param = null,bool createCanCall = false)
    {
        BaseUI ui = null;
        mDicUI.TryGetValue(uiName,out ui);
        if (ui == null)
        {
            cmdList.Add(Command.CreateAndShowCmd(uiName,type,listener, param, createCanCall));
        }
        else
        {
            cmdList.Add(Command.ShowCmd(uiName, listener, param, createCanCall));
        }
    }
    /// <summary>
    /// 显示一个界面
    /// </summary>
    /// <param name="cmd"></param>
    private void _ShowUI(Command cmd)
    {
        BaseUI ui = null;
        mDicUI.TryGetValue(cmd.uiName, out ui);
        if (ui != null)
        {
            if (cmd.listener != null)
            {
                cmd.listener.FiniSh(ui);
            }
            ui.Show();
        }
    }
    #endregion
    #region  隐藏UI
    /// <summary>
    /// 隐藏这个UI
    /// </summary>
    /// <param name="uiName"></param>
    public void HideUI(string uiName)
    {
        cmdList.Add(Command.HideCmd(uiName));
    }
    private void _HideUI(Command cmd)
    {
        Debug.Log("_HideUI " + cmd.uiName);
        BaseUI ui = null;
        mDicUI.TryGetValue(cmd.uiName, out ui);
        if (ui != null)
        {
            ui.Hide();
        }
    }
#endregion
    #region  删除UI
    /// <summary>
    /// 删除UI
    /// </summary>
    /// <param name="uiName">UI名称</param>
    public void DestroyUI(string uiName)
    {
        cmdList.Add(Command.DestroyCmd(uiName));
    }
    private void _DestroyUI(Command cmd)
    {
        BaseUI ui = null;
        mDicUI.TryGetValue(cmd.uiName, out ui);
        if (ui != null)
        {
            mDicUI.Remove(ui.UIName);
            Destroy(ui.CacheGameObject);
        }
    }
    #endregion
    // Update is called every frame, if the MonoBehaviour is enabled.
    void Update() 
    {
        if (cmdList.Count > 0)
        {
            Command tempCmd = null;
            tempCmd = cmdList[0];
            if (tempCmd == null)
            {
                cmdList.RemoveAt(0);
            }
            else
            {
                switch(tempCmd.cmdType)
                {
                    case Command.CmdType.CreateAndShow:
                        _Create(tempCmd);
                        break;
                    case Command.CmdType.Create:
                        _Create(tempCmd);
                        break;
                    case Command.CmdType.Destroy:
                        _DestroyUI(tempCmd);
                        break;
                    case Command.CmdType.Hide:
                        _HideUI(tempCmd);
                        break;
                    case Command.CmdType.Show:
                        _ShowUI(tempCmd);
                        break;
                }
                cmdList.RemoveAt(0);
            }
        }
    }
    /// <summary>
    /// UI资源加载完成的回调
    /// </summary>
    public class LoadResFinish : IResLoadListener
    {
        /// <summary>
        /// 命令
        /// </summary>
        public Command cmd;
        public LoadResFinish(Command _cmd)
        {
            cmd = _cmd;
        }
        public void Finish(object asset)
        {
            if (cmd == null)
            {
                return;
            }
            GameObject go = Instantiate<GameObject>(asset as GameObject);
            go.SetActive(false);
            BaseUI ui =  go.AddComponent(cmd.type) as BaseUI;
            ui.UIInit();
            ui.UIName = cmd.uiName;
            go.gameObject.name = ui.UIName;
            ui.CacheTransform.SetParent(UIMgr.Instance.UIROOT, false);
            UIMgr.Instance.AddUI(ui);
            if (cmd.cmdType == Command.CmdType.CreateAndShow)
            {
                UIMgr.Instance.ShowUI(cmd.uiName, cmd.type, cmd.listener);
            }
            else if (cmd.createCanCall && cmd.listener != null)
            {
                cmd.listener.FiniSh(ui);
            }
        }
        public void Failure()
        {
            if (cmd.createCanCall && cmd.listener != null)
            {
                cmd.listener.Failure();
            }
        }
    }
    /// <summary>
    /// 界面加载回调
    /// </summary>
    public interface ILoadUIListener
    {
        void FiniSh(BaseUI ui);
        void Failure();
    }
    /// <summary>
    /// 操作UI命令集
    /// </summary>
    public class Command
    {
        /// <summary>
        /// 命令类型
        /// </summary>
        public enum CmdType
        {
            /// <summary>
            /// 创建
            /// </summary>
            CreateAndShow,
            /// <summary>
            /// 创建
            /// </summary>
            Create,
            /// <summary>
            /// 显示或者刷新
            /// </summary>
            Show,
            /// <summary>
            /// 隐藏
            /// </summary>
            Hide,
            /// <summary>
            /// 删除
            /// </summary>
            Destroy,
        }
        /// <summary>
        /// UI名称
        /// </summary>
        public string uiName;
        /// <summary>
        /// 要绑定的脚本
        /// </summary>
        public Type type;
        /// <summary>
        /// 加载完成之后的回调
        /// </summary>
        public ILoadUIListener listener;
        /// <summary>
        /// 要传入的数据
        /// </summary>
        public object param;
        /// <summary>
        /// 命令类型
        /// </summary>
        public CmdType cmdType;
        /// <summary>
        /// 创建时候需要回调
        /// </summary>
        public bool createCanCall = true;
        /// <summary>
        /// 获取一个显示的命令
        /// </summary>
        /// <param name="_uiName">UI名称</param>
        /// <param name="_param">要传入的参数</param>
        public static Command CreateAndShowCmd(string uiName, Type type, ILoadUIListener listener, object param , bool createCanCall)
        {
            Command cmd = new Command(CmdType.CreateAndShow, uiName, type);
            cmd.createCanCall = createCanCall;
            cmd.listener = listener;
            cmd.type = type;
            cmd.param = param;
            return cmd;
        }
        /// <summary>
        /// 获取一个显示的命令
        /// </summary>
        /// <param name="_uiName">UI名称</param>
        /// <param name="_param">要传入的参数</param>
        public static Command ShowCmd(string _uiName,ILoadUIListener listener ,object _param, bool _createCanCall)
        {
            Command cmd = new Command(CmdType.Show, _uiName, _param);
            cmd.createCanCall = _createCanCall;
            cmd.listener = listener;
            return cmd;
        }
        /// <summary>
        /// 获取一个创建的命令
        /// </summary>
        /// <param name="_type">要绑定的脚本</param>
        /// <param name="_listener">加载完成之后的回调</param>
        public static Command CreateCmd(Type _type,string _uiName, ILoadUIListener _listener)
        {
            return new Command(CmdType.Create, _uiName, _type, _listener);
        }
        /// <summary>
        /// 获取一个隐藏命令
        /// </summary>
        /// <param name="_uiName">要隐藏的UI名称</param>
        /// <returns></returns>
        public static Command HideCmd(string _uiName)
        {
            return new Command(CmdType.Hide, _uiName,null);
        }
        /// <summary>
        /// 获取一个删除的命令
        /// </summary>
        /// <param name="_uiName">UI名称</param>
        /// <returns></returns>
        public static Command DestroyCmd(string _uiName)
        {
            return new Command(CmdType.Destroy, _uiName, null);
        }
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="_cmdType">命令类型</param>
        /// <param name="_uiName">UI名称</param>
        /// <param name="_param">要传入的参数</param>
        public Command(CmdType _cmdType, string _uiName, object _param)
        {
            uiName = _uiName;
            cmdType = _cmdType;
            param = _param;
        }
        /// <summary>
        /// 构造
        /// </summary>
        /// <param name="_cmdType">命令类型</param>
        /// <param name="_type">要绑定的脚本</param>
        /// <param name="_listener">加载完成之后的回调</param>
        public Command(CmdType _cmdType,string _uiName,Type _type,ILoadUIListener _listener)
        {
            cmdType = _cmdType;
            type = _type;
            listener = _listener;
            uiName = _uiName;
        }
    }
}
来自:https://blog.csdn.net/u013108312/article/details/52355425

如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引