简易的EventManager实现

  • Post author:
  • Post category:其他


首先,这篇博文是参考了

http://blog.sina.com.cn/s/blog_5b6cb9500102uypp.html

这个文章作者的思路而设计的。经过自己的理解后,模仿了一个消息系统给自己用,下面谈谈对这个系统的认识和看法。

我所制作的EventManager的核心是:

1.把我们游戏中所有用到的方法,全部放在一个枚举中,如下:

public enum GameEvent
{
    //这里是定义玩家的事件
    PLAYER_ATTACK,
    PLAYER_DEATH,
    PLAYER_SPEAK,
    PLAYER_GAINLIFE,
    PLAYER_REDUCELIFE,


    //这里是定义怪物的事件
    ENEMY_DEATH,
    ENEMY_ATTACK,
    ENEMY_REDUCELIFE,
}

2.建立一个字典容器,然后在游戏初始化的时候把游戏中所有的事件即上面的GameEvent全部保存在字典的key中,这样我们就把游戏内所有的事件名全部放在了一个字典中。代码如下:

//建立委托
    public delegate void CommonEvent(object data);

    //建立事件列表
    public Dictionary<GameEvent, CommonEvent> eventDic = new Dictionary<GameEvent, CommonEvent>();

    /// <summary>
    /// 事件初始化
    /// </summary>
    public void InitEvent()
    {

        foreach (GameEvent key in Enum.GetValues(typeof(GameEvent)))
        {
            AddEvent(key);
        }
    }
        /// <summary>
    /// 添加一个回调事件
    /// </summary>
    /// <param name="key"></param>
    void AddEvent(GameEvent key)
    {
        eventDic.Add(key, delegate (object data) { });
    }

3.我们给这个类添加3个行为,分别是注册事件,执行事件,解绑事件。它们的作用就是我们在游戏中将所有需要实体和对象,当他们需要和其他对象进行交互的时候,我们首先将所有对象的每一个交互行为添加在GameEvent枚举中,然后在这些对象进行初始化的时候,把这个对象的行为利用EventManager的注册方法注册进入字典中;在对象需要相互交互的时候,我们直接调用EventManager的执行事件调用相应的方法;在对话被销毁的时候我们执行EventManager的解绑事件方法,如下:

    /// <summary>
    /// 触发事件
    /// </summary>
    /// <param name="key"></param>
    /// <param name="param"></param>
    public void TriggerEvent(GameEvent key,object param)
    {
        if (eventDic.ContainsKey(key))
        {
            eventDic[key](param);
        }
        else
        {
            Debug.LogError("没有定义的事件:" + key);
        }
    }

    /// <summary>
    /// 绑定一个事件
    /// </summary>
    /// <param name="key">事件的key</param>
    /// <param name="attachEvent">事件的方法</param>
    public void AttachEvent(GameEvent key , CommonEvent attachEvent)
    {
        if (eventDic.ContainsKey(key))
        {
            eventDic[key] += attachEvent;
        }
        else
        {
            Debug.LogError("没有定义的事件:" + key);
        }
    }

    /// <summary>
    /// 解绑一个事件
    /// </summary>
    /// <param name="key">事件的key</param>
    /// <param name="detachEvent">要解除的事件方法</param>
    public void DetachEvent(GameEvent key , CommonEvent detachEvent)
    {
        if (eventDic.ContainsKey(key))
        {
            eventDic[key] -= detachEvent;
        }
        else
        {
            Debug.LogError("没有定义的事件:" + key);
        }
    }

以下是完整代码:

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

public enum GameEvent
{
    //这里是定义玩家的事件
    PLAYER_ATTACK,
    PLAYER_DEATH,
    PLAYER_SPEAK,
    PLAYER_GAINLIFE,
    PLAYER_REDUCELIFE,


    //这里是定义怪物的事件
    ENEMY_DEATH,
    ENEMY_ATTACK,
    ENEMY_REDUCELIFE,
}
public class EventManager{

    private static EventManager _instance;
    public static EventManager Instance
    {
        get
        {
            if(_instance == null)
            {
                _instance = new EventManager();
            }
            return _instance;
        }
    }

    //建立委托
    public delegate void CommonEvent(object data);

    //建立事件列表
    public Dictionary<GameEvent, CommonEvent> eventDic = new Dictionary<GameEvent, CommonEvent>();

    /// <summary>
    /// 事件初始化
    /// </summary>
    public void InitEvent()
    {

        foreach (GameEvent key in Enum.GetValues(typeof(GameEvent)))
        {
            AddEvent(key);
        }
    }

    /// <summary>
    /// 添加一个回调事件
    /// </summary>
    /// <param name="key"></param>
    void AddEvent(GameEvent key)
    {
        eventDic.Add(key, delegate (object data) { });
    }

    /// <summary>
    /// 触发事件
    /// </summary>
    /// <param name="key"></param>
    /// <param name="param"></param>
    public void TriggerEvent(GameEvent key,object param)
    {
        if (eventDic.ContainsKey(key))
        {
            eventDic[key](param);
        }
        else
        {
            Debug.LogError("没有定义的事件:" + key);
        }
    }

    /// <summary>
    /// 绑定一个事件
    /// </summary>
    /// <param name="key">事件的key</param>
    /// <param name="attachEvent">事件的方法</param>
    public void AttachEvent(GameEvent key , CommonEvent attachEvent)
    {
        if (eventDic.ContainsKey(key))
        {
            eventDic[key] += attachEvent;
        }
        else
        {
            Debug.LogError("没有定义的事件:" + key);
        }
    }

    /// <summary>
    /// 解绑一个事件
    /// </summary>
    /// <param name="key">事件的key</param>
    /// <param name="detachEvent">要解除的事件方法</param>
    public void DetachEvent(GameEvent key , CommonEvent detachEvent)
    {
        if (eventDic.ContainsKey(key))
        {
            eventDic[key] -= detachEvent;
        }
        else
        {
            Debug.LogError("没有定义的事件:" + key);
        }
    }
}

——————2017.03.31更新——————————————

上文中的EventManager是一个多播委托。比如说我们游戏中有多个怪物的实例,若我们触发了怪物的死亡事件,那么所有的怪物都会执行相应的死亡方法。此时,必须在怪物的死亡方法中做if条件判断,来判断自己是否达到了死亡条件。若不做判断,则会立即死亡。

因此,在有多个实例的时候,在通知实例执行一定的方法时,必须设置好充分的条件判断,这样才不会出问题。



版权声明:本文为q568360447原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。