Advanced CSharp Messenger 属于C#事件的一种。 维基百科中由详细的说明http://wiki.unity3d.com/index.php?title=Advanced_CSharp_Messenger 

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

    private Script script;void Awake(){GameObject cube = GameObject.Find("Cube");script = cube.GetComponent<Script>();}void Update(){if(Input.GetMouseButtonDown(0)){script.DoSomething();}}

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

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

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

CallBack.cs

public delegate void Callback();
public delegate void Callback<T>(T arg1);
public delegate void Callback<T, U>(T arg1, U arg2);
public delegate void Callback<T, U, V>(T arg1, U arg2, V arg3);

Message.cs

/** Advanced C# messenger by Ilya Suzdalnitski. V1.0* * Based on Rod Hyde's "CSharpMessenger" and Magnus Wolffelt's "CSharpMessenger Extended".* * Features:* Prevents a MissingReferenceException because of a reference to a destroyed message handler.* Option to log all messages* Extensive error detection, preventing silent bugs* * Usage examples:1. Messenger.AddListener<GameObject>("prop collected", PropCollected);Messenger.Broadcast<GameObject>("prop collected", prop);2. Messenger.AddListener<float>("speed changed", SpeedChanged);Messenger.Broadcast<float>("speed changed", 0.5f);* * Messenger cleans up its evenTable automatically upon loading of a new level.* * Don't forget that the messages that should survive the cleanup, should be marked with Messenger.MarkAsPermanent(string)* *///#define LOG_ALL_MESSAGES
//#define LOG_ADD_LISTENER
//#define LOG_BROADCAST_MESSAGE
#define REQUIRE_LISTENERusing System;
using System.Collections.Generic;
using UnityEngine;static internal class Messenger {#region Internal variables//Disable the unused variable warning
#pragma warning disable 0414//Ensures that the MessengerHelper will be created automatically upon start of the game.static private MessengerHelper messengerHelper = ( new GameObject("MessengerHelper") ).AddComponent< MessengerHelper >();
#pragma warning restore 0414static public Dictionary<string, Delegate> eventTable = new Dictionary<string, Delegate>();//Message handlers that should never be removed, regardless of calling Cleanupstatic public List< string > permanentMessages = new List< string > ();#endregion#region Helper methods//Marks a certain message as permanent.static public void MarkAsPermanent(string eventType) {
#if LOG_ALL_MESSAGESDebug.Log("Messenger MarkAsPermanent \t\"" + eventType + "\"");
#endifpermanentMessages.Add( eventType );}static public void Cleanup(){
#if LOG_ALL_MESSAGESDebug.Log("MESSENGER Cleanup. Make sure that none of necessary listeners are removed.");
#endifList< string > messagesToRemove = new List<string>();foreach (KeyValuePair<string, Delegate> pair in eventTable) {bool wasFound = false;foreach (string message in permanentMessages) {if (pair.Key == message) {wasFound = true;break;}}if (!wasFound)messagesToRemove.Add( pair.Key );}foreach (string message in messagesToRemove) {eventTable.Remove( message );}}static public void PrintEventTable(){Debug.Log("\t\t\t=== MESSENGER PrintEventTable ===");foreach (KeyValuePair<string, Delegate> pair in eventTable) {Debug.Log("\t\t\t" + pair.Key + "\t\t" + pair.Value);}Debug.Log("\n");}#endregion#region Message logging and exception throwingstatic public void OnListenerAdding(string eventType, Delegate listenerBeingAdded) {
#if LOG_ALL_MESSAGES || LOG_ADD_LISTENERDebug.Log("MESSENGER OnListenerAdding \t\"" + eventType + "\"\t{" + listenerBeingAdded.Target + " -> " + listenerBeingAdded.Method + "}");
#endifif (!eventTable.ContainsKey(eventType)) {eventTable.Add(eventType, null );}Delegate d = eventTable[eventType];if (d != null && d.GetType() != listenerBeingAdded.GetType()) {throw new 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));}}static public void OnListenerRemoving(string eventType, Delegate listenerBeingRemoved) {
#if LOG_ALL_MESSAGESDebug.Log("MESSENGER OnListenerRemoving \t\"" + eventType + "\"\t{" + listenerBeingRemoved.Target + " -> " + listenerBeingRemoved.Method + "}");
#endifif (eventTable.ContainsKey(eventType)) {Delegate d = eventTable[eventType];if (d == null) {throw new ListenerException(string.Format("Attempting to remove listener with for event type \"{0}\" but current listener is null.", eventType));} else if (d.GetType() != listenerBeingRemoved.GetType()) {throw new 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));}} else {throw new ListenerException(string.Format("Attempting to remove listener for type \"{0}\" but Messenger doesn't know about this event type.", eventType));}}static public void OnListenerRemoved(string eventType) {if (eventTable[eventType] == null) {eventTable.Remove(eventType);}}static public void OnBroadcasting(string eventType) {
#if REQUIRE_LISTENERif (!eventTable.ContainsKey(eventType)) {throw new BroadcastException(string.Format("Broadcasting message \"{0}\" but no listener found. Try marking the message with Messenger.MarkAsPermanent.", eventType));}
#endif}static public BroadcastException CreateBroadcastSignatureException(string eventType) {return new BroadcastException(string.Format("Broadcasting message \"{0}\" but listeners have a different signature than the broadcaster.", eventType));}public class BroadcastException : Exception {public BroadcastException(string msg): base(msg) {}}public class ListenerException : Exception {public ListenerException(string msg): base(msg) {}}#endregion#region AddListener//No parametersstatic public void AddListener(string eventType, Callback handler) {OnListenerAdding(eventType, handler);eventTable[eventType] = (Callback)eventTable[eventType] + handler;}//Single parameterstatic public void AddListener<T>(string eventType, Callback<T> handler) {OnListenerAdding(eventType, handler);eventTable[eventType] = (Callback<T>)eventTable[eventType] + handler;}//Two parametersstatic public void AddListener<T, U>(string eventType, Callback<T, U> handler) {OnListenerAdding(eventType, handler);eventTable[eventType] = (Callback<T, U>)eventTable[eventType] + handler;}//Three parametersstatic public void AddListener<T, U, V>(string eventType, Callback<T, U, V> handler) {OnListenerAdding(eventType, handler);eventTable[eventType] = (Callback<T, U, V>)eventTable[eventType] + handler;}#endregion#region RemoveListener//No parametersstatic public void RemoveListener(string eventType, Callback handler) {OnListenerRemoving(eventType, handler);   eventTable[eventType] = (Callback)eventTable[eventType] - handler;OnListenerRemoved(eventType);}//Single parameterstatic public void RemoveListener<T>(string eventType, Callback<T> handler) {OnListenerRemoving(eventType, handler);eventTable[eventType] = (Callback<T>)eventTable[eventType] - handler;OnListenerRemoved(eventType);}//Two parametersstatic public void RemoveListener<T, U>(string eventType, Callback<T, U> handler) {OnListenerRemoving(eventType, handler);eventTable[eventType] = (Callback<T, U>)eventTable[eventType] - handler;OnListenerRemoved(eventType);}//Three parametersstatic public void RemoveListener<T, U, V>(string eventType, Callback<T, U, V> handler) {OnListenerRemoving(eventType, handler);eventTable[eventType] = (Callback<T, U, V>)eventTable[eventType] - handler;OnListenerRemoved(eventType);}#endregion#region Broadcast//No parametersstatic public void Broadcast(string eventType) {
#if LOG_ALL_MESSAGES || LOG_BROADCAST_MESSAGEDebug.Log("MESSENGER\t" + System.DateTime.Now.ToString("hh:mm:ss.fff") + "\t\t\tInvoking \t\"" + eventType + "\"");
#endifOnBroadcasting(eventType);Delegate d;if (eventTable.TryGetValue(eventType, out d)) {Callback callback = d as Callback;if (callback != null) {callback();} else {throw CreateBroadcastSignatureException(eventType);}}}//Single parameterstatic public void Broadcast<T>(string eventType, T arg1) {
#if LOG_ALL_MESSAGES || LOG_BROADCAST_MESSAGEDebug.Log("MESSENGER\t" + System.DateTime.Now.ToString("hh:mm:ss.fff") + "\t\t\tInvoking \t\"" + eventType + "\"");
#endifOnBroadcasting(eventType);Delegate d;if (eventTable.TryGetValue(eventType, out d)) {Callback<T> callback = d as Callback<T>;if (callback != null) {callback(arg1);} else {throw CreateBroadcastSignatureException(eventType);}}}//Two parametersstatic public void Broadcast<T, U>(string eventType, T arg1, U arg2) {
#if LOG_ALL_MESSAGES || LOG_BROADCAST_MESSAGEDebug.Log("MESSENGER\t" + System.DateTime.Now.ToString("hh:mm:ss.fff") + "\t\t\tInvoking \t\"" + eventType + "\"");
#endifOnBroadcasting(eventType);Delegate d;if (eventTable.TryGetValue(eventType, out d)) {Callback<T, U> callback = d as Callback<T, U>;if (callback != null) {callback(arg1, arg2);} else {throw CreateBroadcastSignatureException(eventType);}}}//Three parametersstatic public void Broadcast<T, U, V>(string eventType, T arg1, U arg2, V arg3) {
#if LOG_ALL_MESSAGES || LOG_BROADCAST_MESSAGEDebug.Log("MESSENGER\t" + System.DateTime.Now.ToString("hh:mm:ss.fff") + "\t\t\tInvoking \t\"" + eventType + "\"");
#endifOnBroadcasting(eventType);Delegate d;if (eventTable.TryGetValue(eventType, out d)) {Callback<T, U, V> callback = d as Callback<T, U, V>;if (callback != null) {callback(arg1, arg2, arg3);} else {throw CreateBroadcastSignatureException(eventType);}}}#endregion
}//This manager will ensure that the messenger's eventTable will be cleaned up upon loading of a new level.
public sealed class MessengerHelper : MonoBehaviour {void Awake (){DontDestroyOnLoad(gameObject);    }//Clean up eventTable every time a new level loads.public void OnDisable() {Messenger.Cleanup();}
}

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

    void Update(){if(Input.GetMouseButtonDown(0)){Messenger.Broadcast("Send");}}

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

using UnityEngine;
using System.Collections;public class Script : MonoBehaviour {void Awake(){Messenger.AddListener( "Send", DoSomething );}public void DoSomething(){Debug.Log("DoSomething");}
}

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

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

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

    void Update(){if(Input.GetMouseButtonDown(0)){GameObject cube = GameObject.Find("Cube");Messenger.Broadcast<GameObject,int>("Send",cube,1980);}}

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

using UnityEngine;
using System.Collections;public class Script : MonoBehaviour {void Awake(){Messenger.AddListener<GameObject,int>( "Send", DoSomething );}public void DoSomething(GameObject obj,int i){Debug.Log("name " + obj.name + " id =" + i);}
}

如果传递一个参数<T>

两个参数<T,T>

三个参数<T,T,T>   

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

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

C#使用Advanced CSharp Messenger相关推荐

  1. Unity消息简易框架 Advanced C# messenger

    Unity消息简易框架 Advanced C# messenger Unity C# 消息机制  [转载 雨凇MOMO博客] https://www.xuanyusong.com/archives/2 ...

  2. 【转】NGUI研究院之三种方式监听NGUI的事件方法(七)

    NGUI事件的种类很多,比如点击.双击.拖动.滑动等等,他们处理事件的原理几乎万全一样,本文只用按钮来举例. 1.直接监听事件 把下面脚本直接绑定在按钮上,当按钮点击时就可以监听到,这种方法不太好很不 ...

  3. (转)NGUI研究院之三种方式监听NGUI的事件方法

    NGUI事件的种类很多,比如点击.双击.拖动.滑动等等,他们处理事件的原理几乎万全一样,本文只用按钮来举例. 1.直接监听事件 把下面脚本直接绑定在按钮上,当按钮点击时就可以监听到,这种方法不太好很不 ...

  4. Unity3D学习之路

    1.准备C#的开发环境 VS2015, Unity3D 5.5.1 2.准备通信协议 protobuf 3.3.0 具体请参考:Protobuf 3.3 使用总结 3.引入日志系统 :C#日志系统 L ...

  5. 我手中的电子书书目清单(开始提供BT下载)

    13G电子书开始提供BT下载,下载说明及BT种子下载见我另一Blog网页:http://blog.csdn.net/yiyuan/archive/2005/10/16/504747.aspx 我手中的 ...

  6. yiyuan编程电子书系列(目录及种子)

    感觉不错,整个一个电子书库,与大家一起分享一下 BT下载地址: YiYuan编程电子书系列1 http://nnv.dl1.btchina.net/download.php?s=38fff1692d9 ...

  7. 仿LOL项目开发第四天

    ---恢复内容开始--- 仿LOL项目开发第四天 by草帽 上节讲了几乎所有的更新版本的逻辑,那么这节课我们来补充界面框架的搭建的讲解. 我们知道游戏中的每个界面都有自己的一个类型:比如登陆界面,创建 ...

  8. Android中Messenger进程间通信

    基于消息的进程间通信的方式,不需要编写aidl文件,使用更加简单方便. 客户端和服务端都用Messenger来发送数据,用Handler来处理数据.Messenger处理数据依靠Handler,所以是 ...

  9. 命令行编译运行CSharp文件

    命令行编译运行CSharp文件 找到csc.exe所在的路径.如我本机上为"C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727" 在环境变量 ...

最新文章

  1. 科研费4年翻3倍,全球科研队伍突破8000人,滴滴致力打造出行领域核心技术
  2. python3的3D实战 -基于panda3d(3)
  3. 【JAVA】java 堆溢出分析
  4. 进程篇—进程整理(转)
  5. python+grpc+yolo 目标检测实践
  6. Cocos2D场景编辑器
  7. 【最全】BliBli,视频下载方法汇总!【最新】
  8. 设计一个具有大纯时延时间的一阶惯性环节的计算机控制系统,计算机控制课程设计——大纯时延一阶惯性环节温度控制系统...
  9. 软件架构师的沟通修炼
  10. android horizontalscrollview属性,Android 实例讲解HorizontalScrollView实现左右滑动
  11. 终于解决 归递调用 警告,其实程序没有 归递调用*** WARNING L13: RECURSIVE CALL TO SEGMENT
  12. The following signatures couldn‘t be verified because the public key is not available: NO_PUBKEY
  13. 十字路口待转区什么用_左转待转区的几种违章 稍不注意你绝对就要中招
  14. jetson连接PCF8591读取模拟电压值
  15. 移动硬盘出现好多类似5b823bbe980da233a005c83a\update的文件,0字节,删不掉
  16. uCLinux系统分析
  17. Android笔试题大全(持续更新中),安卓应用开发项目
  18. 【TS TSP】基于matlab禁忌搜索算法求解31城市旅行商问题【含Matlab源码 1143期】
  19. python与c语言的区别-c语言和python之间有什么区别
  20. CES 2019 前夕 | 万字长文回顾智能驾驶进化史

热门文章

  1. mac共享文件夹 linux,一文搞定 Linux,Mac,Windows 的 NFS 网络文件共享服务部署
  2. 如何将Linux还原为win10,技术编辑为你解说win10系统Linux Bash命令的还原步骤
  3. php本地文件包含漏洞,php文件包含漏洞利用小结
  4. IDEA隐藏不需要的文件
  5. 一台计算机连接两个投影,用一台PC控制四台投影 投影机多屏幕演示功能详解
  6. linux大量生成测试文件,Shell脚本创建指定大小文件的测试数据
  7. 天津大学计算机专硕_「20考研」计算机考研专业课变动汇总
  8. echart雷达图数据图形的填充颜色_数据可视化,职场数据分析都需要哪些常用的图表?...
  9. 使用管理员账户远程连接WMQ7.5的“AMQ4036”错误
  10. Centos系统查看版本