Unity消息简易框架 Advanced C# messenger

摘要:
正文AdvancedCSharpMessenger属于C#事件类型。维基百科包含详细描述http://wiki.unity3d.com/index.php?title=Advanced_CSharp_Messenger上周的一天,一位朋友碰巧问我我的知识,于是我研究了一下并将其发布在我的博客上,帮助了他和我自己!AdvancedCSharpMessenger可以将游戏对象作为参数发送。首先创建一个多维数据集对象,然后将脚本绑定到此对象。脚本中有一个名为DoSomething()的方法。privateScriptscript;voidAwake(){GameObjectcube=GameObject.Find;script=cube.GetComponent<script>();}voidUpdate(){if{script.DSomething();}}代码相对简单,因此我不做评论。)现在我们使用AdvancedCSharpMessenger调用事件。首次复制消息。cs和回调。根据Wikipedia,将cs输入到您的项目中。
Unity消息简易框架 Advanced C# messenger
Unity C# 消息机制 

【转载 雨凇MOMO博客】 https://www.xuanyusong.com/archives/2165

Tips

在寻找Unity下好用的消息事件框架的时候无意中发现该框架,十分简易,但又用起来特别方便。公司VR游戏中试了下,真滴方便。也不造轮子了,直接转载雨凇大佬的博客,就当是Mark一下,方便以后学习。

正文

Advanced CSharp Messenger 属于C#事件的一种。 维基百科中由详细的说明http://wiki.unity3d.com/index.php?title=Advanced_CSharp_Messenger 上周的一天刚巧有朋友问到我这一块的知识,那么我研究出来将它贴在博客中,帮助了他也帮助我自己!哇咔咔。

Advanced CSharp Messenger的特点可以将游戏对象做为参数发送。到底Advanced CSharp Messenger有什么用呢?先创建一个立方体对象,然后把Script脚本绑定在这个对象中。脚本中有一个方法叫DoSomething()。写一段简单的代码,通常我们在调用方法的时候需要这样来写。

  1. private Script script; 
  2. voidAwake() 

  3. GameObject cube = GameObject.Find("Cube"); 
  4. script = cube.GetComponent<Script>(); 

  5.  
  6. voidUpdate() 

  7. if(Input.GetMouseButtonDown(0)) 

  8. script.DoSomething(); 


  9.  

代码比较简单,我就不注释了。 原理就是先获取游戏对象,接着获取脚本组件对象,最后通过脚本组件对象去调用对应脚本中的方法,这样的调用方法我们称之为直接调用。

这个例子中我只调用了一个对象的方法,如果说有成千上万个对象,那么这样调用是不是感觉自己的代码非常的丑?因为你需要一个一个的获取对象然后获取脚本组件然后在调用方法。。。。。 (想想都恐怖!!)

下面我们在用Advanced CSharp Messenger来实现事件的调用。按照维基百科中首先把Message.cs 和Callback.cs拷贝在你的工程中。

CallBack.cs

  1. publicdelegatevoidCallback()
  2. publicdelegatevoid Callback<T>(T arg1); 
  3. publicdelegatevoid Callback<T, U>(T arg1, U arg2); 
  4. publicdelegatevoid Callback<T, U, V>(T arg1, U arg2, V arg3); 

Message.cs

  1. /* 
  2. * Advanced C# messenger by Ilya Suzdalnitski. V1.0 
  3. *  
  4. * Based on Rod Hyde's "CSharpMessenger" and Magnus Wolffelt's "CSharpMessenger Extended". 
  5. *  
  6. * Features: 
  7. * Prevents a MissingReferenceException because of a reference to a destroyed message handler. 
  8. * Option to log all messages 
  9. * Extensive error detection, preventing silent bugs 
  10. *  
  11. * Usage examples: 
  12. 1. Messenger.AddListener<GameObject>("prop collected", PropCollected); 
  13. Messenger.Broadcast<GameObject>("prop collected", prop); 
  14. 2. Messenger.AddListener<float>("speed changed", SpeedChanged); 
  15. Messenger.Broadcast<float>("speed changed", 0.5f); 
  16. *  
  17. * Messenger cleans up its evenTable automatically upon loading of a new level. 
  18. *  
  19. * Don't forget that the messages that should survive the cleanup, should be marked with Messenger.MarkAsPermanent(string) 
  20. *  
  21. */ 
  22.  
  23. //#define LOG_ALL_MESSAGES 
  24. //#define LOG_ADD_LISTENER 
  25. //#define LOG_BROADCAST_MESSAGE 
  26. #define REQUIRE_LISTENER 
  27.  
  28. using System; 
  29. using System.Collections.Generic; 
  30. using UnityEngine; 
  31.  
  32. staticinternalclassMessenger
  33. #region Internal variables 
  34.  
  35. //Disable the unused variable warning 
  36. #pragmawarning disable 0414 
  37. //Ensures that the MessengerHelper will be created automatically upon start of the game. 
  38. staticprivate MessengerHelper messengerHelper = ( new GameObject("MessengerHelper") ).AddComponent< MessengerHelper >(); 
  39. #pragmawarning restore 0414 
  40.  
  41. staticpublic Dictionary<string, Delegate> eventTable = new Dictionary<string, Delegate>(); 
  42.  
  43. //Message handlers that should never be removed, regardless of calling Cleanup 
  44. staticpublic List< string > permanentMessages = new List< string > (); 
  45. #endregion 
  46. #region Helper methods 
  47. //Marks a certain message as permanent. 
  48. staticpublicvoidMarkAsPermanent(string eventType)
  49. #if LOG_ALL_MESSAGES 
  50. Debug.Log("Messenger MarkAsPermanent "" + eventType + """); 
  51. #endif 
  52.  
  53. permanentMessages.Add( eventType ); 

  54.  
  55. staticpublicvoidCleanup() 

  56. #if LOG_ALL_MESSAGES 
  57. Debug.Log("MESSENGER Cleanup. Make sure that none of necessary listeners are removed."); 
  58. #endif 
  59.  
  60. List< string > messagesToRemove = new List<string>(); 
  61.  
  62. foreach (KeyValuePair<string, Delegate> pair in eventTable) { 
  63. bool wasFound = false
  64.  
  65. foreach (string message in permanentMessages) { 
  66. if (pair.Key == message) { 
  67. wasFound = true
  68. break


  69.  
  70. if (!wasFound) 
  71. messagesToRemove.Add( pair.Key ); 

  72.  
  73. foreach (string message in messagesToRemove) { 
  74. eventTable.Remove( message ); 


  75.  
  76. staticpublicvoidPrintEventTable() 

  77. Debug.Log(" === MESSENGER PrintEventTable ==="); 
  78.  
  79. foreach (KeyValuePair<string, Delegate> pair in eventTable) { 
  80. Debug.Log(" " + pair.Key + " " + pair.Value); 

  81.  
  82. Debug.Log(" "); 

  83. #endregion 
  84.  
  85. #region Message logging and exception throwing 
  86. staticpublicvoidOnListenerAdding(string eventType, Delegate listenerBeingAdded)
  87. #if LOG_ALL_MESSAGES || LOG_ADD_LISTENER 
  88. Debug.Log("MESSENGER OnListenerAdding "" + eventType + "" {" + listenerBeingAdded.Target + " -> " + listenerBeingAdded.Method + "}"); 
  89. #endif 
  90.  
  91. if (!eventTable.ContainsKey(eventType)) { 
  92. eventTable.Add(eventType, null ); 

  93.  
  94. Delegate d = eventTable[eventType]; 
  95. if (d != null && d.GetType() != listenerBeingAdded.GetType()) { 
  96. thrownew ListenerException(string.Format("Attempting to add listener with inconsistent signature for event type {0}. Current listeners have type {1} and listener being added has type {2}", eventType, d.GetType().Name, listenerBeingAdded.GetType().Name)); 


  97.  
  98. staticpublicvoidOnListenerRemoving(string eventType, Delegate listenerBeingRemoved)
  99. #if LOG_ALL_MESSAGES 
  100. Debug.Log("MESSENGER OnListenerRemoving "" + eventType + "" {" + listenerBeingRemoved.Target + " -> " + listenerBeingRemoved.Method + "}"); 
  101. #endif 
  102.  
  103. if (eventTable.ContainsKey(eventType)) { 
  104. Delegate d = eventTable[eventType]; 
  105.  
  106. if (d == null) { 
  107. thrownew ListenerException(string.Format("Attempting to remove listener with for event type "{0}" but current listener is null.", eventType)); 
  108. } elseif (d.GetType() != listenerBeingRemoved.GetType()) { 
  109. thrownew ListenerException(string.Format("Attempting to remove listener with inconsistent signature for event type {0}. Current listeners have type {1} and listener being removed has type {2}", eventType, d.GetType().Name, listenerBeingRemoved.GetType().Name)); 

  110. } else
  111. thrownew ListenerException(string.Format("Attempting to remove listener for type "{0}" but Messenger doesn't know about this event type.", eventType)); 


  112.  
  113. staticpublicvoidOnListenerRemoved(string eventType)
  114. if (eventTable[eventType] == null) { 
  115. eventTable.Remove(eventType); 


  116.  
  117. staticpublicvoidOnBroadcasting(string eventType)
  118. #if REQUIRE_LISTENER 
  119. if (!eventTable.ContainsKey(eventType)) { 
  120. thrownew BroadcastException(string.Format("Broadcasting message "{0}" but no listener found. Try marking the message with Messenger.MarkAsPermanent.", eventType)); 

  121. #endif 

  122.  
  123. staticpublic BroadcastException CreateBroadcastSignatureException(string eventType)
  124. returnnew BroadcastException(string.Format("Broadcasting message "{0}" but listeners have a different signature than the broadcaster.", eventType)); 

  125.  
  126. publicclassBroadcastException : Exception
  127. publicBroadcastException(string msg) 
  128. : base(msg)


  129.  
  130. publicclassListenerException : Exception
  131. publicListenerException(string msg) 
  132. : base(msg)


  133. #endregion 
  134.  
  135. #region AddListener 
  136. //No parameters 
  137. staticpublicvoidAddListener(string eventType, Callback handler)
  138. OnListenerAdding(eventType, handler); 
  139. eventTable[eventType] = (Callback)eventTable[eventType] + handler; 

  140.  
  141. //Single parameter 
  142. staticpublicvoid AddListener<T>(string eventType, Callback<T> handler) { 
  143. OnListenerAdding(eventType, handler); 
  144. eventTable[eventType] = (Callback<T>)eventTable[eventType] + handler; 

  145.  
  146. //Two parameters 
  147. staticpublicvoid AddListener<T, U>(string eventType, Callback<T, U> handler) { 
  148. OnListenerAdding(eventType, handler); 
  149. eventTable[eventType] = (Callback<T, U>)eventTable[eventType] + handler; 

  150.  
  151. //Three parameters 
  152. staticpublicvoid AddListener<T, U, V>(string eventType, Callback<T, U, V> handler) { 
  153. OnListenerAdding(eventType, handler); 
  154. eventTable[eventType] = (Callback<T, U, V>)eventTable[eventType] + handler; 

  155. #endregion 
  156.  
  157. #region RemoveListener 
  158. //No parameters 
  159. staticpublicvoidRemoveListener(string eventType, Callback handler)
  160. OnListenerRemoving(eventType, handler);  
  161. eventTable[eventType] = (Callback)eventTable[eventType] - handler; 
  162. OnListenerRemoved(eventType); 

  163.  
  164. //Single parameter 
  165. staticpublicvoid RemoveListener<T>(string eventType, Callback<T> handler) { 
  166. OnListenerRemoving(eventType, handler); 
  167. eventTable[eventType] = (Callback<T>)eventTable[eventType] - handler; 
  168. OnListenerRemoved(eventType); 

  169.  
  170. //Two parameters 
  171. staticpublicvoid RemoveListener<T, U>(string eventType, Callback<T, U> handler) { 
  172. OnListenerRemoving(eventType, handler); 
  173. eventTable[eventType] = (Callback<T, U>)eventTable[eventType] - handler; 
  174. OnListenerRemoved(eventType); 

  175.  
  176. //Three parameters 
  177. staticpublicvoid RemoveListener<T, U, V>(string eventType, Callback<T, U, V> handler) { 
  178. OnListenerRemoving(eventType, handler); 
  179. eventTable[eventType] = (Callback<T, U, V>)eventTable[eventType] - handler; 
  180. OnListenerRemoved(eventType); 

  181. #endregion 
  182.  
  183. #region Broadcast 
  184. //No parameters 
  185. staticpublicvoidBroadcast(string eventType)
  186. #if LOG_ALL_MESSAGES || LOG_BROADCAST_MESSAGE 
  187. Debug.Log("MESSENGER " + System.DateTime.Now.ToString("hh:mm:ss.fff") + " Invoking "" + eventType + """); 
  188. #endif 
  189. OnBroadcasting(eventType); 
  190.  
  191. Delegate d; 
  192. if (eventTable.TryGetValue(eventType, out d)) { 
  193. Callback callback = d as Callback; 
  194.  
  195. if (callback != null) { 
  196. callback(); 
  197. } else
  198. throw CreateBroadcastSignatureException(eventType); 



  199.  
  200. //Single parameter 
  201. staticpublicvoid Broadcast<T>(string eventType, T arg1) { 
  202. #if LOG_ALL_MESSAGES || LOG_BROADCAST_MESSAGE 
  203. Debug.Log("MESSENGER " + System.DateTime.Now.ToString("hh:mm:ss.fff") + " Invoking "" + eventType + """); 
  204. #endif 
  205. OnBroadcasting(eventType); 
  206.  
  207. Delegate d; 
  208. if (eventTable.TryGetValue(eventType, out d)) { 
  209. Callback<T> callback = d as Callback<T>; 
  210.  
  211. if (callback != null) { 
  212. callback(arg1); 
  213. } else
  214. throw CreateBroadcastSignatureException(eventType); 



  215.  
  216. //Two parameters 
  217. staticpublicvoid Broadcast<T, U>(string eventType, T arg1, U arg2) { 
  218. #if LOG_ALL_MESSAGES || LOG_BROADCAST_MESSAGE 
  219. Debug.Log("MESSENGER " + System.DateTime.Now.ToString("hh:mm:ss.fff") + " Invoking "" + eventType + """); 
  220. #endif 
  221. OnBroadcasting(eventType); 
  222.  
  223. Delegate d; 
  224. if (eventTable.TryGetValue(eventType, out d)) { 
  225. Callback<T, U> callback = d as Callback<T, U>; 
  226.  
  227. if (callback != null) { 
  228. callback(arg1, arg2); 
  229. } else
  230. throw CreateBroadcastSignatureException(eventType); 



  231.  
  232. //Three parameters 
  233. staticpublicvoid Broadcast<T, U, V>(string eventType, T arg1, U arg2, V arg3) { 
  234. #if LOG_ALL_MESSAGES || LOG_BROADCAST_MESSAGE 
  235. Debug.Log("MESSENGER " + System.DateTime.Now.ToString("hh:mm:ss.fff") + " Invoking "" + eventType + """); 
  236. #endif 
  237. OnBroadcasting(eventType); 
  238.  
  239. Delegate d; 
  240. if (eventTable.TryGetValue(eventType, out d)) { 
  241. Callback<T, U, V> callback = d as Callback<T, U, V>; 
  242.  
  243. if (callback != null) { 
  244. callback(arg1, arg2, arg3); 
  245. } else
  246. throw CreateBroadcastSignatureException(eventType); 



  247. #endregion 

  248.  
  249. //This manager will ensure that the messenger's eventTable will be cleaned up upon loading of a new level. 
  250. publicsealedclassMessengerHelper : MonoBehaviour
  251. voidAwake () 

  252. DontDestroyOnLoad(gameObject);  

  253.  
  254. //Clean up eventTable every time a new level loads. 
  255. publicvoidOnDisable()
  256. Messenger.Cleanup(); 


然后就可以开始使用了,Messager.Broadcast()这样就好比我们发送了一条广播。

  1. voidUpdate() 

  2. if(Input.GetMouseButtonDown(0)) 

  3. Messenger.Broadcast("Send"); 


在需要这条广播的类中来接受它,同样是刚刚说的Script类。接受广播的标志是 Messager.AddListener()参数1表示广播的名称,参数2表示广播所调用的方法。

  1. using UnityEngine; 
  2. using System.Collections; 
  3.  
  4. publicclassScript : MonoBehaviour
  5.  
  6. voidAwake() 

  7. Messenger.AddListener( "Send", DoSomething ); 

  8. publicvoidDoSomething() 

  9. Debug.Log("DoSomething"); 


这样一来,只要发送名称为”Send”的方法,就可以在别的类中接收它了。

我们在说说如何通过广播来传递参数,这也是那天那个哥们主要问我的问题。(其实是维基百科上写的不是特别特别的清楚,那哥们误解了)在Callback中可以看出参数最多可以是三个,参数的类型是任意类型,也就是说我们不仅能传递 int float bool 还能传递gameObject类型。

如下所示,发送广播的时候传递了两个参数,参数1是一个游戏对象,参数2是一个int数值。

  1. voidUpdate() 

  2. if(Input.GetMouseButtonDown(0)) 

  3. GameObject cube = GameObject.Find("Cube"); 
  4. Messenger.Broadcast<GameObject,int>("Send",cube,1980); 


然后是接受的地方 参数用<>存在一起。游戏对象也可以完美的传递。

  1. using UnityEngine; 
  2. using System.Collections; 
  3.  
  4. publicclassScript : MonoBehaviour
  5.  
  6. voidAwake() 

  7. Messenger.AddListener<GameObject,int>( "Send", DoSomething ); 

  8. publicvoidDoSomething(GameObject obj,int i) 

  9. Debug.Log("name " + obj.name + " id =" + i); 


如果传递一个参数

两个参数<T,T>

三个参数<T,T,T>

怎么样使用起来还是挺简单的吧?

我觉得项目中最好不要大量的使用代理事件这类的方法(根据需求而定),虽然可以让你的代码非常的简洁,但是它的效率不高大概比直接调用慢5-倍左右吧,就好比美好的东西一定都有瑕疵一样。 还记得Unity自身也提供了一种发送消息的方法吗?,用过的都知道效率也非常低下,虽然我们看不到它具体实现的源码是如何实现的,但是我觉得原理可能也是这样的。 欢迎和大家一起讨论与学习。

免责声明:文章转载自《Unity消息简易框架 Advanced C# messenger》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇flask 需要下载的包10个顶级的CSS UI开源框架下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

微信小程序学习笔记(二)--框架-全局及页面配置

描述和功能 框架提供了自己的视图层描述语言 WXML 和 WXSS,以及基于 JavaScript 的逻辑层框架,并在视图层与逻辑层间提供了数据传输和事件系统,让开发者能够专注于数据与逻辑。 响应的数据绑定 框架的核心是一个响应的数据绑定系统。 整个小程序框架系统分为两部分:视图层(View)和逻辑层(App Service)。 页面管理 框架 管理了整个...

web快速开发框架 WebBuilder 8.7发布

一个强大的web开发框架往往与他开发速度有关,他需要帮助程序员尽可能快的完成项目的同时确保它的安全性,WebBuilder是基于Java的web开发框架,其核心开发目标是开发迅速,代码少,学习简单,功能强大,轻量级,易扩展。 WebBuilder开发框架具有以下特点: 1. 框架的主架构为基于Jaa 的 BS 架构。 2. 后台 ORM支持 多种模式。...

.net 类库如何为类库添加两个框架依赖

需求:为满足一个类库被不同框架的程序调用,需要类库支持多框架 1.新建一个 .netstandard2.0类库项目,名为:TCM.SuperX.YM.Contracts 2.右键点击类库名称,选择“编辑TCM.SuperX.YM.Contracts.csproj” 3.修改TragetFramework标签内容,加入其它框架名称及版本号 原始: 修改后:...

开源一个功能完整的SpringBoot项目框架

开源一个功能完整的SpringBoot项目框架福利来了,给大家带来一个福利。最近想了解一下有关Spring Boot的开源项目,看了很多开源的框架,大多是一些demo或者是一个未成形的项目,基本功能都不完整,尤其是用户权限和菜单方面几乎没有完整的。 想到我之前做的框架,里面通用模块有:用户模块,权限模块,菜单模块,功能模块也齐全了,每一个功能都是完整的。...

如何测试基于Unity3D引擎的游戏

版权声明:允许转载,但转载必须保留原链接;请勿用作商业或者非法用途 由于游戏的界面是通过游戏引擎渲染出来的,游戏界面没有系统原生的控件信息,所以对于游戏,我们需要接入 poco-sdk 才能获取到游戏界面中的控件信息。下面以Unity开发的手游为例,介绍如何在Android和iOS平台进行连接。 Android 平台 从poco sdk repo将Unit...

关于 Unity UGUI 中修改 Mask 组件下 Image 等子节点组件的材质无效的问题

前几天同事做了一个效果,希望在原本使用了遮罩组件 Mask 的技能图标(让技能图标变成圆形)上在添加一个置灰的功能,但问题来了:因为是动态根据游戏中玩家的条件才动态置灰,以修改 Mask 下子节点 Image 组件的材质来实现的,但是实际上怎么修改也不起作用,呈现出的效果都只停留在第一次运行时的样子。 一开始我也以为是 shader 的问题,修改的 pro...