Unity3D研究院之通过C#使用Advanced CSharp Messenger

 

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

01private Script script;
02void Awake()
03{
04    GameObject cube = GameObject.Find("Cube");
05    script = cube.GetComponent<Script>();
06}
07void Update()
08{
09    if(Input.GetMouseButtonDown(0))
10    {
11        script.DoSomething();
12    }
13}

 

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

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

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

CallBack.cs

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

 Message.cs

001/*
002 * Advanced C# messenger by Ilya Suzdalnitski. V1.0
003 
004 * Based on Rod Hyde's "CSharpMessenger" and Magnus Wolffelt's "CSharpMessenger Extended".
005 
006 * Features:
007    * Prevents a MissingReferenceException because of a reference to a destroyed message handler.
008    * Option to log all messages
009    * Extensive error detection, preventing silent bugs
010 
011 * Usage examples:
012    1. Messenger.AddListener<GameObject>("prop collected", PropCollected);
013       Messenger.Broadcast<GameObject>("prop collected", prop);
014    2. Messenger.AddListener<float>("speed changed", SpeedChanged);
015       Messenger.Broadcast<float>("speed changed", 0.5f);
016 
017 * Messenger cleans up its evenTable automatically upon loading of a new level.
018 
019 * Don't forget that the messages that should survive the cleanup, should be marked with Messenger.MarkAsPermanent(string)
020 
021 */
022  
023//#define LOG_ALL_MESSAGES
024//#define LOG_ADD_LISTENER
025//#define LOG_BROADCAST_MESSAGE
026#define REQUIRE_LISTENER
027  
028using System;
029using System.Collections.Generic;
030using UnityEngine;
031  
032static internal class Messenger {
033    #region Internal variables
034  
035    //Disable the unused variable warning
036#pragma warning disable 0414
037    //Ensures that the MessengerHelper will be created automatically upon start of the game.
038    static private MessengerHelper messengerHelper = ( new GameObject("MessengerHelper") ).AddComponent< MessengerHelper >();
039#pragma warning restore 0414
040  
041    static public Dictionary<string, Delegate> eventTable = new Dictionary<string, Delegate>();
042  
043    //Message handlers that should never be removed, regardless of calling Cleanup
044    static public List< string > permanentMessages = new List< string > ();
045    #endregion
046    #region Helper methods
047    //Marks a certain message as permanent.
048    static public void MarkAsPermanent(string eventType) {
049#if LOG_ALL_MESSAGES
050        Debug.Log("Messenger MarkAsPermanent \t\"" + eventType + "\"");
051#endif
052  
053        permanentMessages.Add( eventType );
054    }
055  
056    static public void Cleanup()
057    {
058#if LOG_ALL_MESSAGES
059        Debug.Log("MESSENGER Cleanup. Make sure that none of necessary listeners are removed.");
060#endif
061  
062        List< string > messagesToRemove = new List<string>();
063  
064        foreach (KeyValuePair<string, Delegate> pair in eventTable) {
065            bool wasFound = false;
066  
067            foreach (string message in permanentMessages) {
068                if (pair.Key == message) {
069                    wasFound = true;
070                    break;
071                }
072            }
073  
074            if (!wasFound)
075                messagesToRemove.Add( pair.Key );
076        }
077  
078        foreach (string message in messagesToRemove) {
079            eventTable.Remove( message );
080        }
081    }
082  
083    static public void PrintEventTable()
084    {
085        Debug.Log("\t\t\t=== MESSENGER PrintEventTable ===");
086  
087        foreach (KeyValuePair<string, Delegate> pair in eventTable) {
088            Debug.Log("\t\t\t" + pair.Key + "\t\t" + pair.Value);
089        }
090  
091        Debug.Log("\n");
092    }
093    #endregion
094  
095    #region Message logging and exception throwing
096    static public void OnListenerAdding(string eventType, Delegate listenerBeingAdded) {
097#if LOG_ALL_MESSAGES || LOG_ADD_LISTENER
098        Debug.Log("MESSENGER OnListenerAdding \t\"" + eventType + "\"\t{" + listenerBeingAdded.Target + " -> " + listenerBeingAdded.Method + "}");
099#endif
100  
101        if (!eventTable.ContainsKey(eventType)) {
102            eventTable.Add(eventType, null );
103        }
104  
105        Delegate d = eventTable[eventType];
106        if (d != null && d.GetType() != listenerBeingAdded.GetType()) {
107            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));
108        }
109    }
110  
111    static public void OnListenerRemoving(string eventType, Delegate listenerBeingRemoved) {
112#if LOG_ALL_MESSAGES
113        Debug.Log("MESSENGER OnListenerRemoving \t\"" + eventType + "\"\t{" + listenerBeingRemoved.Target + " -> " + listenerBeingRemoved.Method + "}");
114#endif
115  
116        if (eventTable.ContainsKey(eventType)) {
117            Delegate d = eventTable[eventType];
118  
119            if (d == null) {
120                throw new ListenerException(string.Format("Attempting to remove listener with for event type \"{0}\" but current listener is null.", eventType));
121            } else if (d.GetType() != listenerBeingRemoved.GetType()) {
122                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));
123            }
124        } else {
125            throw new ListenerException(string.Format("Attempting to remove listener for type \"{0}\" but Messenger doesn't know about this event type.", eventType));
126        }
127    }
128  
129    static public void OnListenerRemoved(string eventType) {
130        if (eventTable[eventType] == null) {
131            eventTable.Remove(eventType);
132        }
133    }
134  
135    static public void OnBroadcasting(string eventType) {
136#if REQUIRE_LISTENER
137        if (!eventTable.ContainsKey(eventType)) {
138            throw new BroadcastException(string.Format("Broadcasting message \"{0}\" but no listener found. Try marking the message with Messenger.MarkAsPermanent.", eventType));
139        }
140#endif
141    }
142  
143    static public BroadcastException CreateBroadcastSignatureException(string eventType) {
144        return new BroadcastException(string.Format("Broadcasting message \"{0}\" but listeners have a different signature than the broadcaster.", eventType));
145    }
146  
147    public class BroadcastException : Exception {
148        public BroadcastException(string msg)
149            : base(msg) {
150        }
151    }
152  
153    public class ListenerException : Exception {
154        public ListenerException(string msg)
155            : base(msg) {
156        }
157    }
158    #endregion
159  
160    #region AddListener
161    //No parameters
162    static public void AddListener(string eventType, Callback handler) {
163        OnListenerAdding(eventType, handler);
164        eventTable[eventType] = (Callback)eventTable[eventType] + handler;
165    }
166  
167    //Single parameter
168    static public void AddListener<T>(string eventType, Callback<T> handler) {
169        OnListenerAdding(eventType, handler);
170        eventTable[eventType] = (Callback<T>)eventTable[eventType] + handler;
171    }
172  
173    //Two parameters
174    static public void AddListener<T, U>(string eventType, Callback<T, U> handler) {
175        OnListenerAdding(eventType, handler);
176        eventTable[eventType] = (Callback<T, U>)eventTable[eventType] + handler;
177    }
178  
179    //Three parameters
180    static public void AddListener<T, U, V>(string eventType, Callback<T, U, V> handler) {
181        OnListenerAdding(eventType, handler);
182        eventTable[eventType] = (Callback<T, U, V>)eventTable[eventType] + handler;
183    }
184    #endregion
185  
186    #region RemoveListener
187    //No parameters
188    static public void RemoveListener(string eventType, Callback handler) {
189        OnListenerRemoving(eventType, handler);   
190        eventTable[eventType] = (Callback)eventTable[eventType] - handler;
191        OnListenerRemoved(eventType);
192    }
193  
194    //Single parameter
195    static public void RemoveListener<T>(string eventType, Callback<T> handler) {
196        OnListenerRemoving(eventType, handler);
197        eventTable[eventType] = (Callback<T>)eventTable[eventType] - handler;
198        OnListenerRemoved(eventType);
199    }
200  
201    //Two parameters
202    static public void RemoveListener<T, U>(string eventType, Callback<T, U> handler) {
203        OnListenerRemoving(eventType, handler);
204        eventTable[eventType] = (Callback<T, U>)eventTable[eventType] - handler;
205        OnListenerRemoved(eventType);
206    }
207  
208    //Three parameters
209    static public void RemoveListener<T, U, V>(string eventType, Callback<T, U, V> handler) {
210        OnListenerRemoving(eventType, handler);
211        eventTable[eventType] = (Callback<T, U, V>)eventTable[eventType] - handler;
212        OnListenerRemoved(eventType);
213    }
214    #endregion
215  
216    #region Broadcast
217    //No parameters
218    static public void Broadcast(string eventType) {
219#if LOG_ALL_MESSAGES || LOG_BROADCAST_MESSAGE
220        Debug.Log("MESSENGER\t" + System.DateTime.Now.ToString("hh:mm:ss.fff") + "\t\t\tInvoking \t\"" + eventType + "\"");
221#endif
222        OnBroadcasting(eventType);
223  
224        Delegate d;
225        if (eventTable.TryGetValue(eventType, out d)) {
226            Callback callback = d as Callback;
227  
228            if (callback != null) {
229                callback();
230            } else {
231                throw CreateBroadcastSignatureException(eventType);
232            }
233        }
234    }
235  
236    //Single parameter
237    static public void Broadcast<T>(string eventType, T arg1) {
238#if LOG_ALL_MESSAGES || LOG_BROADCAST_MESSAGE
239        Debug.Log("MESSENGER\t" + System.DateTime.Now.ToString("hh:mm:ss.fff") + "\t\t\tInvoking \t\"" + eventType + "\"");
240#endif
241        OnBroadcasting(eventType);
242  
243        Delegate d;
244        if (eventTable.TryGetValue(eventType, out d)) {
245            Callback<T> callback = d as Callback<T>;
246  
247            if (callback != null) {
248                callback(arg1);
249            } else {
250                throw CreateBroadcastSignatureException(eventType);
251            }
252        }
253    }
254  
255    //Two parameters
256    static public void Broadcast<T, U>(string eventType, T arg1, U arg2) {
257#if LOG_ALL_MESSAGES || LOG_BROADCAST_MESSAGE
258        Debug.Log("MESSENGER\t" + System.DateTime.Now.ToString("hh:mm:ss.fff") + "\t\t\tInvoking \t\"" + eventType + "\"");
259#endif
260        OnBroadcasting(eventType);
261  
262        Delegate d;
263        if (eventTable.TryGetValue(eventType, out d)) {
264            Callback<T, U> callback = d as Callback<T, U>;
265  
266            if (callback != null) {
267                callback(arg1, arg2);
268            } else {
269                throw CreateBroadcastSignatureException(eventType);
270            }
271        }
272    }
273  
274    //Three parameters
275    static public void Broadcast<T, U, V>(string eventType, T arg1, U arg2, V arg3) {
276#if LOG_ALL_MESSAGES || LOG_BROADCAST_MESSAGE
277        Debug.Log("MESSENGER\t" + System.DateTime.Now.ToString("hh:mm:ss.fff") + "\t\t\tInvoking \t\"" + eventType + "\"");
278#endif
279        OnBroadcasting(eventType);
280  
281        Delegate d;
282        if (eventTable.TryGetValue(eventType, out d)) {
283            Callback<T, U, V> callback = d as Callback<T, U, V>;
284  
285            if (callback != null) {
286                callback(arg1, arg2, arg3);
287            } else {
288                throw CreateBroadcastSignatureException(eventType);
289            }
290        }
291    }
292    #endregion
293}
294  
295//This manager will ensure that the messenger's eventTable will be cleaned up upon loading of a new level.
296public sealed class MessengerHelper : MonoBehaviour {
297    void Awake ()
298    {
299        DontDestroyOnLoad(gameObject);  
300    }
301  
302    //Clean up eventTable every time a new level loads.
303    public void OnDisable() {
304        Messenger.Cleanup();
305    }
306}

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

1void Update()
2{
3    if(Input.GetMouseButtonDown(0))
4    {
5        Messenger.Broadcast("Send");
6    }
7}

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

01using UnityEngine;
02using System.Collections;
03  
04public class Script : MonoBehaviour {
05  
06    void Awake()
07    {
08        Messenger.AddListener( "Send", DoSomething );
09    }
10    public void DoSomething()
11    {
12        Debug.Log("DoSomething");
13    }
14}

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

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

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

1void Update()
2{
3    if(Input.GetMouseButtonDown(0))
4    {
5        GameObject cube = GameObject.Find("Cube");
6        Messenger.Broadcast<GameObject,int>("Send",cube,1980);
7    }
8}

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

01using UnityEngine;
02using System.Collections;
03  
04public class Script : MonoBehaviour {
05  
06    void Awake()
07    {
08        Messenger.AddListener<GameObject,int>( "Send", DoSomething );
09    }
10    public void DoSomething(GameObject obj,int i)
11    {
12        Debug.Log("name " + obj.name + " id =" + i);
13    }
14}

 

如果传递一个参数<T>

两个参数<T,T>

三个参数<T,T,T>   

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值