Unity 3D 消息事件系统 NotificationCenter、CEventDispatcher事件分发机制

版本:unity 5.4.1  语言:C#

 

实战核心技术这本书来到了第三章,这里给了一个消息事件系统,这是几乎每一个游戏系统都会用到的一个常用技术,非常好用,但如果你add之后忘记remove的话。。。相信每个使用过它的人都经历过这样的痛苦。

 

闲话不多说,书中类的名字是CEventDispatcher,而我会按照我的习惯来实现一遍,就叫做NotificationCenter,对,cocos中的名称。

 

在看书之前,我自己也写过一个,是依靠NGUI中的EventDelegate写的,然后调用传递链也是自己写来调用,看起来还是比较复杂的,而书上的实现就非常简洁了。

 

下面是代码:

using UnityEngine;
using System;
using System.Collections;
using System.Collections.Generic;

// 消息的类型
public enum NotifyType
{
    PLAYER_ON_HURT,
    BLOCK_PLACE,
}

// 消息事件类,使用中传递的信息
public class NotifyEvent
{
    protected Dictionary arguments;  //参数
    protected NotifyType type;  //事件类型
    protected System.Object sender;    //发送者

    // bean函数
    public NotifyType Type
    {
        get { return type; }
        set { type = value; }
    }

    public Dictionary Params
    {
        get { return arguments; }
        set { arguments = value; }
    }

    public System.Object Sender
    {
        get { return sender; }
        set { sender = value; }
    }

    // 常用函数
    public override string ToString()
    {
        return type + " [ " + ((sender == null) ? "null" : sender.ToString()) + " ] ";
    }

    public NotifyEvent Clone()
    {
        return new NotifyEvent(type, arguments, sender);
    }

    // 构造函数
    public NotifyEvent(NotifyType type, System.Object sender)
    {
        Type = type;
        Sender = sender;
        if (arguments == null)
        {
            arguments = new Dictionary();
        }
    }

    public NotifyEvent(NotifyType type, Dictionary args, System.Object sender)
    {
        Type = type;
        arguments = args;
        Sender = sender;
        if (arguments == null)
        {
            arguments = new Dictionary();
        }
    }
}

// 消息监听者,这是一个delegate,也就是一个函数,当事件触发时,对应注册的delegate就会触发
public delegate void EventListenerDelegate(NotifyEvent evt);

// 消息中心
public class NotifacitionCenter
{
    // 单例
    private static NotifacitionCenter instance;
    private NotifacitionCenter() { }
    public static NotifacitionCenter getInstance()
    {
        if (instance == null)
        { 
            instance = new NotifacitionCenter();
        }
        return instance;
    }

    // 成员变量
    Dictionary notifications = new Dictionary() ; // 所有的消息


    // 注册监视
    public void registerObserver(NotifyType type, EventListenerDelegate listener)
    {
        if (listener == null)
        {
            Debug.LogError("registerObserver: listener不能为空");
            return;
        }

        // 将新来的监听者加入调用链,这样只要调用Combine返回的监听者就会调用所有的监听者
        Debug.Log("NotifacitionCenter: 添加监视" + type);

        EventListenerDelegate myListener = null;
        notifications.TryGetValue(type, out myListener);
        notifications[type] = (EventListenerDelegate)Delegate.Combine(myListener, listener);
    }

    // 移除监视
    public void removeObserver(NotifyType type, EventListenerDelegate listener)
    {
        if (listener == null)
        {
            Debug.LogError("removeObserver: listener不能为空");
            return;
        }
        
        // 与添加的思路相同,只是这里是移除操作
        Debug.Log("NotifacitionCenter: 移除监视" + type);
        notifications[type] = (EventListenerDelegate)Delegate.Remove(notifications[type], listener);
    }

    public void removeAllObservers()
    {
        notifications.Clear();
    }

    // 消息触发
    public void postNotification(NotifyEvent evt)
    {
        EventListenerDelegate listenerDelegate;
        if(notifications.TryGetValue(evt.Type, out listenerDelegate))
        {
            try
            {
                // 执行调用所有的监听者
                listenerDelegate(evt);
            }
            catch(System.Exception e)
            {
                throw new Exception(string.Concat(new string[] { "Error dispatching event", evt.Type.ToString(), ": ", e.Message, " ", e.StackTrace }), e);
            }
        }
    }

}

以上就是代码的全部了,实际上就是Delegate的使用,这样一些小项目用这个类往上一套,就能很轻松的实现很多逻辑了。

 

不过最后还是要提醒一下,添加了监听,一定要有删除监听,他们是成对出现的。


你可能感兴趣的:(Unity进阶)