首先,這篇博文是參考了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條件判斷,來判斷自己是否達到了死亡條件。若不做判斷,則會立即死亡。
因此,在有多個實例的時候,在通知實例執行一定的方法時,必須設置好充分的條件判斷,這樣纔不會出問題。