Unity3d游戏开发框架-UI管理类 UIManager
发表于2018-09-12
前面已经给大家介绍了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
Unity3d游戏开发框架系列
5、消息机制