zoukankan      html  css  js  c++  java
  • unity message

    再用unity进行开发过程中,不可避免的用到消息的传递问题,以下介绍几种消息传递的方法:

    (一)拖动赋值

    此方法即为最普通的方法,即把需要引用的游戏物体或者需要引用的组件拖动到相关公有变量的槽上,然后就可以引用相关变量或者方法,继而可以进行消息的传递。也可以用Find方法查找到相关游戏物体,然后获取相关组件以及组件上的方法,变量。

    (二)采用unity GameObject自带的公用方法

    1)public void BroadcastMessage(string methodName, object parameter , SendMessageOptions options)

    此方法为调用其本身以及子游戏物体上名为methodName的同名方法,其中parameter 为methodName方法所需要的参数,此方法可以理解为向下发送消息,即向本身以及子游戏物体发送消息

    2)public void SendMessage(string methodName, object valuel, SendMessageOptions options)

    此方法为调用其本身游戏物体上名为methodName的同名方法,其中parameter 为methodName方法所需要的参数,此方法为平行发送消息。

    3)public void SendMessageUpwards(string methodName, object value, SendMessageOptions options)

    此方法为调用其本身以及父类游戏物体上名为methodName的同名方法,其中parameter 为methodName方法所需要的参数,此方法为向上发送消息。

    (三)向任意位置发送消息

    以上介绍的两种方法都有一定的局限性,在此介绍一种简单的方法,在此需要两个cs文件,分别为Messenger.cs与Callback.cs,相关代码会在后续中给出。通过以下方法进行调用:

            Messenger.AddListener("Method1", OnClicked);//将OnClicked方法绑定到"Method1"上
            Messenger.Broadcast("Method1");//通过"Method1"调用方法将OnClicked方法绑定到
            Messenger.RemoveListener("Method1", OnClicked);//将OnClicked方法从"Method1"移除

    泛型方法如下:

            Messenger.AddListener<string>("Method1", OnClicked);//将OnClicked方法绑定到"Method1"上
            Messenger.Broadcast<string>("Method1","name");//通过"Method1"调用方法将OnClicked方法绑定到
            Messenger.RemoveListener<string>("Method1", OnClicked);//将OnClicked方法从"Method1"移除

    不过此方法效率很低,不可滥用

    (四)通过C#委托

    通过C#多播委托可以实现精准消息传递,而且方便快捷,但是要求对中间细节把控较高,尤其是要在适当的位置解除方法绑定

    附录

    Messenger.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 	"" + 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("			=== MESSENGER PrintEventTable ===");
    
            foreach (KeyValuePair<string, Delegate> pair in eventTable)
            {
                Debug.Log("			" + pair.Key + "		" + pair.Value);
            }
    
            Debug.Log("
    ");
        }
        #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 	"" + eventType + ""	{" + 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 	"" + eventType + ""	{" + 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	" + System.DateTime.Now.ToString("hh:mm:ss.fff") + "			Invoking 	"" + 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	" + System.DateTime.Now.ToString("hh:mm:ss.fff") + "			Invoking 	"" + 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	" + System.DateTime.Now.ToString("hh:mm:ss.fff") + "			Invoking 	"" + 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	" + System.DateTime.Now.ToString("hh:mm:ss.fff") + "			Invoking 	"" + 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();
        }
    }

    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);
  • 相关阅读:
    PostgreSQL数据库
    phpcms网站搬家 至 服务器 完整并且详细过程
    phpcms网页替换验证码功能 及 搜索功能
    用phpcms切换中英文网页的方法(不用解析二级域名)、phpcms完成pc和手机端切换(同一域名)
    php判断手机段登录,以及phpcms手机PC双模板调用
    php 手动搭建环境
    phpcms内容页替换
    phpcms列表页替换
    phpcms首页替换
    phpcms栏目点击选中
  • 原文地址:https://www.cnblogs.com/llstart-new0201/p/7512612.html
Copyright © 2011-2022 走看看