日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > C# >内容正文

C#

Unity消息简易框架 Advanced C# messenger

發布時間:2025/7/14 C# 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Unity消息简易框架 Advanced C# messenger 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

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()。寫一段簡單的代碼,通常我們在調用方法的時候需要這樣來寫。

  • 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_LISTENER?
  • ?
  • using 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 0414?
  • ?
  • static public Dictionary<string, Delegate> eventTable = new Dictionary<string, Delegate>();?
  • ?
  • //Message handlers that should never be removed, regardless of calling Cleanup?
  • static 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_MESSAGES?
  • Debug.Log("Messenger MarkAsPermanent \t\"" + eventType + "\"");?
  • #endif?
  • ?
  • permanentMessages.Add( eventType );?
  • }?
  • ?
  • static public void Cleanup()?
  • {?
  • #if LOG_ALL_MESSAGES?
  • Debug.Log("MESSENGER Cleanup. Make sure that none of necessary listeners are removed.");?
  • #endif?
  • ?
  • List< 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 throwing?
  • static public void OnListenerAdding(string eventType, Delegate listenerBeingAdded) {?
  • #if LOG_ALL_MESSAGES || LOG_ADD_LISTENER?
  • Debug.Log("MESSENGER OnListenerAdding \t\"" + eventType + "\"\t{" + listenerBeingAdded.Target + " -> " + listenerBeingAdded.Method + "}");?
  • #endif?
  • ?
  • if (!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_MESSAGES?
  • Debug.Log("MESSENGER OnListenerRemoving \t\"" + eventType + "\"\t{" + listenerBeingRemoved.Target + " -> " + listenerBeingRemoved.Method + "}");?
  • #endif?
  • ?
  • if (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_LISTENER?
  • if (!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 parameters?
  • static public void AddListener(string eventType, Callback handler) {?
  • OnListenerAdding(eventType, handler);?
  • eventTable[eventType] = (Callback)eventTable[eventType] + handler;?
  • }?
  • ?
  • //Single parameter?
  • static public void AddListener<T>(string eventType, Callback<T> handler) {?
  • OnListenerAdding(eventType, handler);?
  • eventTable[eventType] = (Callback<T>)eventTable[eventType] + handler;?
  • }?
  • ?
  • //Two parameters?
  • static public void AddListener<T, U>(string eventType, Callback<T, U> handler) {?
  • OnListenerAdding(eventType, handler);?
  • eventTable[eventType] = (Callback<T, U>)eventTable[eventType] + handler;?
  • }?
  • ?
  • //Three parameters?
  • static 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 parameters?
  • static public void RemoveListener(string eventType, Callback handler) {?
  • OnListenerRemoving(eventType, handler); ?
  • eventTable[eventType] = (Callback)eventTable[eventType] - handler;?
  • OnListenerRemoved(eventType);?
  • }?
  • ?
  • //Single parameter?
  • static public void RemoveListener<T>(string eventType, Callback<T> handler) {?
  • OnListenerRemoving(eventType, handler);?
  • eventTable[eventType] = (Callback<T>)eventTable[eventType] - handler;?
  • OnListenerRemoved(eventType);?
  • }?
  • ?
  • //Two parameters?
  • static 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 parameters?
  • static 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 parameters?
  • static public void Broadcast(string eventType) {?
  • #if LOG_ALL_MESSAGES || LOG_BROADCAST_MESSAGE?
  • Debug.Log("MESSENGER\t" + System.DateTime.Now.ToString("hh:mm:ss.fff") + "\t\t\tInvoking \t\"" + eventType + "\"");?
  • #endif?
  • OnBroadcasting(eventType);?
  • ?
  • Delegate d;?
  • if (eventTable.TryGetValue(eventType, out d)) {?
  • Callback callback = d as Callback;?
  • ?
  • if (callback != null) {?
  • callback();?
  • } else {?
  • throw CreateBroadcastSignatureException(eventType);?
  • }?
  • }?
  • }?
  • ?
  • //Single parameter?
  • static public void Broadcast<T>(string eventType, T arg1) {?
  • #if LOG_ALL_MESSAGES || LOG_BROADCAST_MESSAGE?
  • Debug.Log("MESSENGER\t" + System.DateTime.Now.ToString("hh:mm:ss.fff") + "\t\t\tInvoking \t\"" + eventType + "\"");?
  • #endif?
  • OnBroadcasting(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 parameters?
  • static public void Broadcast<T, U>(string eventType, T arg1, U arg2) {?
  • #if LOG_ALL_MESSAGES || LOG_BROADCAST_MESSAGE?
  • Debug.Log("MESSENGER\t" + System.DateTime.Now.ToString("hh:mm:ss.fff") + "\t\t\tInvoking \t\"" + eventType + "\"");?
  • #endif?
  • OnBroadcasting(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 parameters?
  • static public void Broadcast<T, U, V>(string eventType, T arg1, U arg2, V arg3) {?
  • #if LOG_ALL_MESSAGES || LOG_BROADCAST_MESSAGE?
  • Debug.Log("MESSENGER\t" + System.DateTime.Now.ToString("hh:mm:ss.fff") + "\t\t\tInvoking \t\"" + eventType + "\"");?
  • #endif?
  • OnBroadcasting(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>

    怎么樣使用起來還是挺簡單的吧?

    我覺得項目中最好不要大量的使用代理事件這類的方法(根據需求而定),雖然可以讓你的代碼非常的簡潔,但是它的效率不高大概比直接調用慢5-倍左右吧,就好比美好的東西一定都有瑕疵一樣。 還記得Unity自身也提供了一種發送消息的方法嗎?,用過的都知道效率也非常低下,雖然我們看不到它具體實現的源碼是如何實現的,但是我覺得原理可能也是這樣的。 歡迎和大家一起討論與學習。

    轉載于:https://www.cnblogs.com/Firepad-magic/p/9484304.html

    總結

    以上是生活随笔為你收集整理的Unity消息简易框架 Advanced C# messenger的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。