什么是消息机制
可以理解为:一个物体发出消息,另外一个或几个物体会接收到这条消息并作出相应的处理。这样做的好处就是模块之间相互独立,降低了模块之间的耦合度,每个脚本都可以有收发消息的能力,把模块之间的调用转化成了收发消息来实现。当然,一个脚本如果要对某个消息做出反应,前提是要添加对该消息的订阅。在消息框架中,通常会使用字典或者链表等数据结构来保存维护所有消息及对应的消息订阅者。
Unity自带的SendMessage
unity自带的消息发送机制SendMessage其实是一种伪监听者模式,它利用的是反射机制,它的效率是很低的,每次调用的时候都会去遍历它自身或者父节点、子节点上对应的方法,因此我们基本不回去用自带的SendMessage。
我们的消息机制框架图
框架主要类
MonoBase:
public class MonoBase : MonoBehaviour
{public virtual void Execute(int eventCode, object message){}}

ManagerBase:
public class ManagerBase : MonoBase
{/// <summary>/// 处理自身的消息/// </summary>/// <param name="eventCode">Event code.</param>/// <param name="message">Message.</param>public override void Execute(int eventCode, object message){if (!dict.ContainsKey(eventCode)){Debug.LogWarning("没有注册 : " + eventCode);return;}//一旦注册过这个消息 给所有的脚本 发过去List<MonoBase> list = dict[eventCode];for (int i = 0; i < list.Count; i++){list[i].Execute(eventCode, message);}}private Dictionary<int,List<MonoBase>> dict = new Dictionary<int, List<MonoBase>>();/// <summary>/// 添加事件/// </summary>/// <param name="eventCode">Event code.</param>/// <param name="mono">Mono.</param>public void Add(int eventCode, MonoBase mono){List<MonoBase> list = null;//之前没有注册过if (!dict.ContainsKey(eventCode)){list = new List<MonoBase>();list.Add(mono);dict.Add(eventCode, list);return;}//之前注册过list = dict[eventCode];list.Add(mono);}/// <summary>/// 添加多个事件///     一个脚本关心多个事件/// </summary>/// <param name="eventCode">Event code.</param>public void Add(int[] eventCodes, MonoBase mono){for (int i = 0; i < eventCodes.Length; i++){Add(eventCodes[i], mono);}}/// <summary>/// 移除事件/// </summary>/// <param name="eventCode">Event code.</param>/// <param name="mono">Mono.</param>public void Remove(int eventCode, MonoBase mono){if (!dict.ContainsKey(eventCode)){Debug.LogWarning("没有这个消息" + eventCode + "注册");return;}List<MonoBase> list = dict[eventCode];if (list.Count == 1)dict.Remove(eventCode);elselist.Remove(mono);}/// <summary>/// 移除多个/// </summary>/// <param name="eventCode">Event code.</param>/// <param name="mono">Mono.</param>public void Remove(int[] eventCodes, MonoBase mono){for (int i = 0; i < eventCodes.Length; i++){Remove(eventCodes[i], mono);}}}

MsgCenter:
/// <summary>
/// 消息处理中心
/// </summary>
public class MsgCenter : MonoBase
{public static MsgCenter Instance = null;void Awake(){Instance = this;gameObject.AddComponent<AudioManager>();gameObject.AddComponent<UIManager>();gameObject.AddComponent<NetManager>();gameObject.AddComponent<CharacterManager>();gameObject.AddComponent<SceneMgr>();DontDestroyOnLoad(gameObject);}/// <summary>/// 参数:区域码、消息、消息参数/// </summary>/// <param name="areaCode"></param>/// <param name="eventCode"></param>/// <param name="message"></param>public void Dispatch(int areaCode, int eventCode, object message){switch (areaCode){case AreaCode.AUDIO:AudioManager.Instance.Execute(eventCode, message);break;case AreaCode.CHARACTER:CharacterManager.Instance.Execute(eventCode, message);break;case AreaCode.NET:NetManager.Instance.Execute(eventCode, message);break;case AreaCode.GAME:break;case AreaCode.UI:UIManager.Instance.Execute(eventCode, message);break;case AreaCode.SCENE:SceneMgr.Instance.Execute(eventCode, message);break;default:break;}}}

AreaCode:
public class AreaCode
{/// <summary>/// UI模块/// </summary>public const int UI = 0;/// <summary>/// GAME模块/// </summary>public const int GAME = 1;/// <summary>/// CHARACTER模块/// </summary>public const int CHARACTER = 2;/// <summary>/// NET模块/// </summary>public const int NET = 3;/// <summary>/// AUDIO模块/// </summary>public const int AUDIO = 4;/// <summary>/// SCENE模块/// </summary>public const int SCENE = 5;//....

}

UI模块实现
UIBase:
public class UIBase : MonoBase
{/// <summary>/// 自身关心的消息集合/// </summary>private List<int> list = new List<int>();/// <summary>/// 绑定一个或多个消息/// </summary>/// <param name="eventCodes">Event codes.</param>protected void Bind(params int[] eventCodes){list.AddRange(eventCodes);UIManager.Instance.Add(list.ToArray(), this);}/// <summary>/// 接触绑定的消息/// </summary>protected void UnBind(){UIManager.Instance.Remove(list.ToArray(), this);list.Clear();}/// <summary>/// 自动移除绑定的消息/// </summary>public  virtual void OnDestroy(){if (list != null)UnBind();}/// <summary>/// 发消息/// </summary>/// <param name="areaCode">Area code.</param>/// <param name="eventCode">Event code.</param>/// <param name="message">Message.</param>public void Dispatch(int areaCode, int eventCode, object message){MsgCenter.Instance.Dispatch(areaCode, eventCode, message);}
}

UIManager:
public class UIManager : ManagerBase
{public static UIManager Instance = null;void Awake(){Instance = this;}
}

UIEvent:

/// <summary>
/// 存储所有的UI消息
/// </summary>
public class UIEvent
{public const int START_PANEL = 0;//设置开始面板的显示public const int REGIST_PANE = 1;//设置注册面板的显示
}

PanelA:

public class PanelA : UIBase
{private void Awake(){Bind(UIEvent.START_PANEL);//添加对消息的关心
    }public override void Execute(int eventCode, object message){switch (eventCode)  //对消息的处理
        {case UIEvent.START_PANEL:DoSomeThing();break;default:break;}}
}

其他模块
类似于UI模块,会有一个模块Manager单例类,继承ManagerBase, 另外有一个模块Base类,继承MonoBase,该模块需要实现收发消息功能的脚本都需要继承这个模块Base类,在脚本的Awke函数中添加对某消息的关心,重写父类的Excute函数,当该消息发出时,会执行该Excute函数,对消息做出相应处理
总结
这套基于消息机制的简易框架优点是很明显的,条理清楚,代码组织明确,移植性高,同时,团队开发时交流也方便,当然,也可以对上述框架进行改进,现在是整个项目的消息都由一个字典来维护,可以考虑每个模块维护自己的消息字典(或者其他数据结构);可以根据消息的区域码,如果是本模块的消息,就直接派给本模块,而不经过消息中心,如果消息属于其他模块,就通过消息中心来转发;可以定义一个消息基类MsgBase,所有消息都继承它。使用框架时,需要注意的是,首先要初始化框架层,再执行其他逻辑。每个需要收发消息的脚本,都必须在Awake函数中添加对消息的关心,在OnDestroy方法中移除对消息的关心。

转载于:https://www.cnblogs.com/IAMTOM/p/9151413.html

基于消息机制的万能框架相关推荐

  1. windows程序消息机制(Winform界面更新有关)--转

    1. Windows程序消息机制 Windows GUI程序是基于消息机制的,有个主线程维护着消息泵.这个消息泵让windows程序生生不息. Windows程序有个消息队列,窗体上的所有消息是这个队 ...

  2. windows程序消息机制(Winform界面更新有关)

    1. Windows程序消息机制 Windows GUI程序是基于消息机制的,有个主线程维护着消息泵.这个消息泵让windows程序生生不息. Windows程序有个消息队列,窗体上的所有消息是这个队 ...

  3. 论文浅尝 | 用于学习知识图谱嵌入的一种基于注意力机制的新型异构 GNN 框架HRAN...

    笔记整理 | 李爽,天津大学 链接:http://hfbix45521e79b0484907sowxo0fubpp9b6xwx.fiiz.eds.tju.edu.cn/stamp/stamp.jsp? ...

  4. 论文浅尝 | ​ADRL:一个基于注意力机制的知识图谱深度强化学习框架

    论文笔记整理:谭亦鸣,东南大学博士. 来源:Knowledge-Based Systems 197 (2020) 105910 链接:https://www.sciencedirect.com/sci ...

  5. Unity 游戏框架搭建 (五) 简易消息机制

    什么是消息机制? 23333333,让我先笑一会. 为什么用消息机制? 三个字,解!!!!耦!!!!合!!!!. 我的框架中的消息机制用例: 1.接收者 using UnityEngine;names ...

  6. 我对于游戏框架的理解——框架,消息机制

    框架: 框架之所以被称为框架.从字面意思上来说是制造了一个框框,也就是规矩.规矩限定了自由. 限定了自由不是局限.而是更加方便管理.--公路是地表的框架.所以车辆才能被有序的管理. 框架方便管理体应该 ...

  7. 基于主动视觉机制的深度学习--一个综合池化框架

    卷积神经网络(CNN)是深度学习的代表算法之一,长期以来被广泛应用于图像识别领域.它是受到了生物处理过程的启发,通过模仿人类视觉系统(HVS)的工作机制,完成各种视觉任务等.但与HVS相比,CNN不能 ...

  8. iOS开发系列--通知与消息机制

    http://www.cocoachina.com/ios/20150318/11364.html 概述 在多数移动应用中任何时候都只能有一个应用程序处于活跃状态,如果其他应用此刻发生了一些用户感兴趣 ...

  9. 基于.NET平台常用的框架整理(转)

    分布式缓存框架: Microsoft Velocity:微软自家分布式缓存服务框架. Memcahed:一套分布式的高速缓存系统,目前被许多网站使用以提升网站的访问速度. Redis:是一个高性能的K ...

最新文章

  1. starrocks问题小结
  2. js倒计时代码最简单的_32个史上最有用的js代码
  3. c# java 语法_Java与C#的语法区别
  4. xcode更新之后插件失效的解决办法
  5. 联想计算机BIOS开启Intel-vx,如何在计算机BIOS或UEFI固件中启用Intel VT-x | MOS86
  6. linux服务器虚拟内存设置,修改Linux服务器虚拟内存Swap大小
  7. 【报告分享】2021新中产人群洞察报告.pdf(附下载链接)
  8. 确认!字节跳动 AI Lab 负责人马维英离职,将赴清华加入张亚勤团队
  9. [SQL面试经验] 经典sql面试题及答案第1期
  10. 谷歌企业邮箱:应用专用密码
  11. element环境插件
  12. 使用kubeadm安装kuberneters
  13. 十一假期,终于过上了理想的生活节奏
  14. SCP,NFS,TFTP的初步认识
  15. ITRON入门学习之实时操作系统的意义与价值
  16. Python编程从入门到实践:动手试一试8-3T恤
  17. Dubbo源码分析-Spring与Dubbo整合原理与源码分析(二)
  18. PageRank算法与特征向量和特征值(eigenvector和eigenvalue)
  19. cordova for android hybrid 程序专题页面宽度大小显示异常问题
  20. OGRE渲染引擎之地形、天空和雾

热门文章

  1. 说一说MVC的CSRF(三)
  2. UltraISO软碟通U盘安装Centos7 的各种报错及解决方案
  3. 英特尔分拆McAfee:31亿美元将多数股权卖给投资公司TPG
  4. 启动MySQL出错: Starting MySQL….. ERROR! The server quit with
  5. 几种常见的数据库连接方法
  6. Git 本地仓库管理
  7. Keystone controller.py routers.py代码解析
  8. Windows 08R2_AD图文详解
  9. window下利用navicat访问Linux下的mariadb数据库
  10. eclipse启动tomcat报错