UIFramework之事件系统实现

来源:互联网 发布:网络中立原则 编辑:程序博客网 时间:2024/05/29 16:21

UIFramework之事件系统实现

在Unity开发中,自定义消息系统经常会被用到,事件系统的实现主要是基于C#委托来完成的。下面介绍的两种实现,一种是利用C#自带的Action委托来实现;第二种是通过自定义一个信息类来作为传递信息的载体,再通过自定义委托来实现的。

实现一:

首先在MessageSystem.cs中实现事件系统的基本功能:

/** Name: MessageSystem.cs* Function: N/A * * Ver     变更日期               负责人                            变更内容* ──────────────────────────────────────────────────────────────────────* V1.0.0  $time$    http://blog.csdn.net/husheng0     * * Copyright (c). All rights reserved.*/using System;using System.Collections.Generic;using UnityEngine;public static class MessageSystem<TKey> where TKey : struct{    //MessageKey对应的注册的委托    private static Dictionary<TKey, List<Delegate>> RegisterMessageDic         = new Dictionary<TKey, List<Delegate>>();    //移出对应的委托    public static void UnRegisterDelegate(TKey MessageKey)    {        RegisterMessageDic.Remove(MessageKey);    }    //清空事件系统已注册事件    public static void CleanEvents()    {        RegisterMessageDic.Clear();    }    //能不能注册该委托    private static bool IsCanRegister(TKey MessageKey, Delegate registerDelegate)    {        List<Delegate> registerDelegateList = null;        if (RegisterMessageDic.TryGetValue(MessageKey, out registerDelegateList))        {            if (null == registerDelegateList || registerDelegateList.Count == 0)                 return true;            foreach (Delegate dele in registerDelegateList)            {                if (dele == registerDelegate) return false;            }        }        else        {            RegisterMessageDic[MessageKey] = new List<Delegate>();        }        return true;    }    #region Action委托    /// <summary>    /// 注册无参Action委托    /// </summary>    /// <param name="MessageKey"></param>    /// <param name="handler"></param>    public static void AddListener(TKey MessageKey, Action handler)    {        if (IsCanRegister(MessageKey, handler))        {            RegisterMessageDic[MessageKey].Add(handler);            Debug.Log("Register" + MessageKey.ToString() + "success");        }        else        {            Debug.LogError("Register" + MessageKey.ToString() + "failure");        }    }    /// <summary>    /// 移除无参Action委托    /// </summary>    /// <param name="MessageKey"></param>    /// <param name="handler"></param>    public static void RemoveListenerer(TKey MessageKey, Action handler)    {        if (!IsCanRegister(MessageKey, handler))        {            RegisterMessageDic[MessageKey].Remove(handler);            Debug.Log("Remove" + MessageKey.ToString() + "success");        }        else        {            Debug.LogError("Remove" + MessageKey.ToString() + "failure");        }    }    /// <summary>    /// 广播无参Action委托    /// </summary>    /// <param name="MessageKey"></param>    public static void Broadcast(TKey MessageKey)    {        List<Delegate> registerDelegateList;        if (RegisterMessageDic.TryGetValue(MessageKey, out registerDelegateList))        {            Action callback;            for (int i = 0; i < registerDelegateList.Count; ++i)            {                try                {                    callback = (registerDelegateList[i]) as Action;                    if (callback != null)                    {                        callback();                    }                }                catch (Exception exp)                {                    Debug.LogException(exp);                }            }        }    }    #endregion    #region Action<T>委托    /// <summary>    /// 注册含一个参数的委托    /// </summary>    /// <typeparam name="T"></typeparam>    /// <param name="MessageKey"></param>    /// <param name="handler"></param>    public static void AddListener<T>(TKey MessageKey, Action<T> handler)    {        if (IsCanRegister(MessageKey, handler))        {            RegisterMessageDic[MessageKey].Add(handler);            Debug.Log("Register" + MessageKey.ToString() + "success");        }        else        {            Debug.LogError("Register" + MessageKey.ToString() + "failure");        }    }    /// <summary>    /// 移除含一个参数的Action委托    /// </summary>    /// <typeparam name="T"></typeparam>    /// <param name="MessageKey"></param>    /// <param name="handler"></param>    public static void RemoveListenerer<T>(TKey MessageKey, Action<T> handler)    {        if (!IsCanRegister(MessageKey, handler))        {            RegisterMessageDic[MessageKey].Remove(handler);            Debug.Log("Remove" + MessageKey.ToString() + "success");        }        else        {            Debug.LogError("Remove" + MessageKey.ToString() + "failure");        }    }    /// <summary>    /// 广播含一个参数的Action委托    /// </summary>    /// <typeparam name="T"></typeparam>    /// <param name="MessageKey"></param>    /// <param name="arg1"></param>    public static void Broadcast<T>(TKey MessageKey, T arg1)    {        List<Delegate> registerDelegateList;        if (RegisterMessageDic.TryGetValue(MessageKey, out registerDelegateList))        {            Action<T> callback;            for (int i = 0; i < registerDelegateList.Count; ++i)            {                try                {                    callback = (registerDelegateList[i]) as Action<T>;                    if (callback != null)                    {                        callback(arg1);                    }                }                catch (Exception exp)                {                    Debug.LogException(exp);                }            }        }    }    #endregion    #region Action<T1,T2>委托    /// <summary>    /// 注册含两个参数的Action委托    /// </summary>    /// <typeparam name="T1"></typeparam>    /// <typeparam name="T2"></typeparam>    /// <param name="MessageKey"></param>    /// <param name="handler"></param>    public static void AddListener<T1, T2>(TKey MessageKey, Action<T1, T2> handler)    {        if (IsCanRegister(MessageKey, handler))        {            RegisterMessageDic[MessageKey].Add(handler);            Debug.Log("Register" + MessageKey.ToString() + "success");        }        else        {            Debug.LogError("Register" + MessageKey.ToString() + "failure");        }    }    /// <summary>    /// 移除含两个参数的Action委托    /// </summary>    /// <typeparam name="T1"></typeparam>    /// <typeparam name="T2"></typeparam>    /// <param name="MessageKey"></param>    /// <param name="handler"></param>    public static void RemoveListenerer<T1, T2>(TKey MessageKey, Action<T1, T2> handler)    {        if (!IsCanRegister(MessageKey, handler))        {            RegisterMessageDic[MessageKey].Remove(handler);            Debug.Log("Remove" + MessageKey.ToString() + "success");        }        else        {            Debug.LogError("Remove" + MessageKey.ToString() + "failure");        }    }    /// <summary>    /// 广播含两个参数的Action委托    /// </summary>    /// <typeparam name="T1"></typeparam>    /// <typeparam name="T2"></typeparam>    /// <param name="MessageKey"></param>    /// <param name="arg1"></param>    /// <param name="arg2"></param>    public static void Broadcast<T1, T2>(TKey MessageKey, T1 arg1, T2 arg2)    {        List<Delegate> registerDelegateList;        if (RegisterMessageDic.TryGetValue(MessageKey, out registerDelegateList))        {            Action<T1, T2> callback;            for (int i = 0; i < registerDelegateList.Count; ++i)            {                try                {                    callback = (registerDelegateList[i]) as Action<T1, T2>;                    if (callback != null)                    {                        callback(arg1, arg2);                    }                }                catch (Exception exp)                {                    Debug.LogException(exp);                }            }        }    }    #endregion}

下面使用两个脚本进行简单的测试:

/// <summary>/// 全局事件/// </summary>public enum MsgTest{    Test1,    Test2,    Test3}

using UnityEngine;using System.Collections;public class MessageSystemTest : MonoBehaviour{    void OnGUI()    {        if (GUI.Button(new Rect(50, 50, 200, 30), "Register Action"))            MessageSystem<MsgTest>.AddListener(MsgTest.Test1, Test1Func);        if (GUI.Button(new Rect(50, 100, 200, 30), "Broadcast Action"))            MessageSystem<MsgTest>.Broadcast(MsgTest.Test1);        if (GUI.Button(new Rect(50, 150, 200, 30), "Remove Action"))            MessageSystem<MsgTest>.RemoveListenerer(MsgTest.Test1, Test1Func);        if (GUI.Button(new Rect(50, 200, 200, 30), "Register Action<T>"))            MessageSystem<MsgTest>.AddListener<int>(MsgTest.Test2, Test2Func);        if (GUI.Button(new Rect(50, 250, 200, 30), "Broadcast Action<T>"))            MessageSystem<MsgTest>.Broadcast<int>(MsgTest.Test2,100);        if (GUI.Button(new Rect(50, 300, 200, 30), "Remove Action<T>"))            MessageSystem<MsgTest>.RemoveListenerer<int>(MsgTest.Test2, Test2Func);        if (GUI.Button(new Rect(50, 350, 200, 30), "Register Action<T1,T2>"))            MessageSystem<MsgTest>.AddListener<int,string>(MsgTest.Test3, Test3Func);        if (GUI.Button(new Rect(50, 400, 200, 30), "Broadcast Action<T1,T2>"))            MessageSystem<MsgTest>.Broadcast<int,string>(MsgTest.Test3,100,"test");        if (GUI.Button(new Rect(50, 450, 200, 30), "Remove Action<T1,T2>"))            MessageSystem<MsgTest>.RemoveListenerer<int,string>(MsgTest.Test3, Test3Func);    }    private void Test1Func()    {        Debug.LogError("--->Test1Func");    }    private void Test2Func(int i)    {        Debug.LogError("--->Test1Func"+i.ToString());    }    private void Test3Func(int i,string str)    {        Debug.LogError("--->Test1Func" + i.ToString()+"  "+str);    }}

测试结果如下图所示:




实现二:

第二种是实现方式与第一种实现方式其实是大同小异:

using System;using System.Collections.Generic;using UnityEngine;public static class MessageCenter{    public delegate void MessageEvent(Message message);    private static Dictionary<string, List<MessageEvent>> MessageEventsDic =        new Dictionary<string, List<MessageEvent>>();    #region Add & Remove Listener    public static void AddListener(string messageName, MessageEvent messageEvent)    {        Debug.Log("AddListener Name : " + messageName);        List<MessageEvent> list = null;        if (MessageEventsDic.ContainsKey(messageName))        {            list = MessageEventsDic[messageName];        }        else        {            list = new List<MessageEvent>();            MessageEventsDic.Add(messageName, list);        }        if (!list.Contains(messageEvent))        {            list.Add(messageEvent);        }    }    public static void RemoveListener(string messageName, MessageEvent messageEvent)    {        Debug.Log("RemoveListener Name : " + messageName);        if (MessageEventsDic.ContainsKey(messageName))        {            List<MessageEvent> list = MessageEventsDic[messageName];            if (list.Contains(messageEvent))            {                list.Remove(messageEvent);            }            if (list.Count <= 0)            {                MessageEventsDic.Remove(messageName);            }        }    }    public static void RemoveAllListener()    {        MessageEventsDic.Clear();    }    #endregion    #region Send Message    public static void SendMessage(Message message)    {        DoMessageDispatcher(message);    }    public static void SendMessage(string name, object sender)    {        SendMessage(new Message(name, sender));    }    public static void SendMessage(string name, object sender, object content)    {        SendMessage(new Message(name, sender, content));    }    public static void SendMessage(string name, object sender, object content, params object[] dicParams)    {        SendMessage(new Message(name, sender, content, dicParams));    }    private static void DoMessageDispatcher(Message message)    {        Debug.Log("DoMessageDispatcher Name : " + message.Name);        if (MessageEventsDic == null || !MessageEventsDic.ContainsKey(message.Name))            return;        List<MessageEvent> list = MessageEventsDic[message.Name];        for (int i = 0; i < list.Count; i++)        {            MessageEvent messageEvent = list[i];            if (null != messageEvent)            {                messageEvent(message);            }        }    }    #endregion}

using System;using System.Collections;using System.Collections.Generic;public class Message : IEnumerable<KeyValuePair<string, object>>{    private Dictionary<string, object> DatasDic = null;    public string Name { get; private set; }    public object Sender { get; private set; }    public object Content { get; set; }    /// <summary>    /// 索引器     /// </summary>    /// <param name="key"></param>    /// <returns></returns>    public object this[string key]    {        get        {            if (null == DatasDic || !DatasDic.ContainsKey(key))                return null;            return DatasDic[key];        }        set        {            if (null == DatasDic)                DatasDic = new Dictionary<string, object>();            if (DatasDic.ContainsKey(key))                DatasDic[key] = value;            else                DatasDic.Add(key, value);        }    }    #region IEnumerable implementation    public IEnumerator<KeyValuePair<string, object>> GetEnumerator()    {        if (null == DatasDic)            yield break;        foreach (KeyValuePair<string, object> kvp in DatasDic)        {            yield return kvp;        }    }    IEnumerator IEnumerable.GetEnumerator()    {        return DatasDic.GetEnumerator();    }    #endregion    #region Message Construction Function    public Message(string name, object sender)    {        Name = name;        Sender = sender;        Content = null;    }    public Message(string name, object sender, object content)    {        Name = name;        Sender = sender;        Content = content;    }    public Message(string name, object sender, object content, params object[] _dicParams)    {        Name = name;        Sender = sender;        Content = content;        if (_dicParams.GetType() == typeof(Dictionary<string, object>))        {            foreach (object _dicParam in _dicParams)            {                foreach (KeyValuePair<string, object> kvp in _dicParam as Dictionary<string, object>)                {                    //DatasDic[kvp.Key] = kvp.Value;  //error                    this[kvp.Key] = kvp.Value;                }            }        }    }    public Message(Message message)    {        Name = message.Name;        Sender = message.Sender;        Content = message.Content;        foreach (KeyValuePair<string, object> kvp in message.DatasDic)        {            this[kvp.Key] = kvp.Value;        }    }    #endregion    #region Add & Remove    public void Add(string key, object value)    {        this[key] = value;    }    public void Remove(string key)    {        if (null != DatasDic && DatasDic.ContainsKey(key))        {            DatasDic.Remove(key);        }    }    #endregion    #region Send    public void Send()    {        MessageCenter.SendMessage(this);    }    #endregion}

该事件系统的关键字就是通过创建的Message里的Name来判断的,所以要注意Name防止重复。

测试文件如下:

using UnityEngine;using System.Collections;public class MessageCenterTest : MonoBehaviour {    private readonly string test = "test";    void Awake()    {        MessageCenter.AddListener(test,OnMessageCome);    }    private void OnMessageCome(Message message)    {        Debug.LogError("--->" + message["gold"]);    }    void OnGUI()    {        if (GUI.Button(new Rect(50, 50, 150, 30), "OnMessageCome"))        {            Message message = new Message(test,this);            message["gold"] = 100;            message.Send();        }    }}


=====================================================================

结束。

0 0
原创粉丝点击