EventManager
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.SceneManagement;
/// <summary>
/// 事件类型枚举
/// </summary>
public enum EVENT_TYPE
{
SPAWBLUEARMY,
SPAWBLUEARMYFINISH,
CLEARSCENE,
};
public class EventManager : SingletonMonoBehaviour<EventManager>
{
#region variables
//事件委托
public delegate void OnEvent(EVENT_TYPE Event_Type, Component Sender, object Param = null);
//存储每个事件类型下的订阅
private Dictionary<EVENT_TYPE, List<OnEvent>> Listeners = new Dictionary<EVENT_TYPE, List<OnEvent>>();
#endregion
//-----------------------------------------------------------
#region methods
void Awake() {
SceneManager.sceneLoaded += OnSceneLoaded;
}
/// <summary>
/// 添加订阅
/// </summary>
public void AddListener(EVENT_TYPE Event_Type, OnEvent Listener)
{
List<OnEvent> ListenList = null;
if (Listeners.TryGetValue(Event_Type, out ListenList))
{
//List exists, so add new item
ListenList.Add(Listener);
return;
}
ListenList = new List<OnEvent>();
ListenList.Add(Listener);
Listeners.Add(Event_Type, ListenList);
}
//-----------------------------------------------------------
/// <summary>
/// 分发事件,调用该事件类型下的所有订阅者的委托方法
/// </summary>
public void PostNotification(EVENT_TYPE Event_Type, Component Sender, object Param = null)
{
List<OnEvent> ListenList = null;
if (!Listeners.TryGetValue(Event_Type, out ListenList))
return;
for (int i = 0; i < ListenList.Count; i++)
{
if (!ListenList[i].Equals(null))
ListenList[i](Event_Type, Sender, Param);
}
}
//-----------------------------------------------------------
public void RemoveEvent(EVENT_TYPE Event_Type)
{
Listeners.Remove(Event_Type);
}
//-----------------------------------------------------------
//移除订阅字典中无效订阅者
public void RemoveRedundancies()
{
Dictionary<EVENT_TYPE, List<OnEvent>> TmpListeners = new Dictionary<EVENT_TYPE, List<OnEvent>>();
foreach (KeyValuePair<EVENT_TYPE, List<OnEvent>> Item in Listeners)
{
for (int i = Item.Value.Count - 1; i >= 0; i--)
{
if (Item.Value[i].Equals(null))
Item.Value.RemoveAt(i);
}
if (Item.Value.Count > 0)
TmpListeners.Add(Item.Key, Item.Value);
}
Listeners = TmpListeners;
}
//单例下换场景不会销毁,因此需要在场景加载后清除无效的订阅
void OnSceneLoaded()
{
RemoveRedundancies();
}
//-----------------------------------------------------------
#endregion
}
使用案例
using UnityEngine;
using System.Collections;
public class EnemyObject : MonoBehaviour
{
//-------------------------------------------------------
//C# accessors for private variables
public int Health
{
get{return _health;}
set
{
//Clamp health between 0-100
_health = Mathf.Clamp(value, 0, 100);
//Post notification - health has been changed
EventManager.Instance.PostNotification(EVENT_TYPE.HEALTH_CHANGE, this, _health);
}
}
//-------------------------------------------------------
public int Ammo
{
get{return _ammo;}
set
{
//Clamp ammo between 0-50
_ammo = Mathf.Clamp(value,0,50);
//Post notification - ammo has been changed
EventManager.Instance.PostNotification(EVENT_TYPE.AMMO_CHANGE, this, _health);
}
}
//-------------------------------------------------------
//Internal variables for health and ammo
private int _health = 100;
private int _ammo = 50;
//-------------------------------------------------------
//Called at start-up
void Start()
{
//Add myself as listener for health change events
EventManager.Instance.AddListener(EVENT_TYPE.HEALTH_CHANGE, OnEvent);
}
//-------------------------------------------------------
// Update is called once per frame
void Update ()
{
//If you press space bar, the health is reduce
if(Input.GetKeyDown(KeyCode.Space))
{
//Take some damage of space bar press
Health -= 5;
}
}
//-------------------------------------------------------
//Called when events happen
public void OnEvent(EVENT_TYPE Event_Type, Component Sender, object Param = null)
{
//Detect event type
switch(Event_Type)
{
case EVENT_TYPE.HEALTH_CHANGE:
OnHealthChange(Sender, (int)Param);
break;
}
}
//-------------------------------------------------------
//Function called when health changes
void OnHealthChange(Component Enemy, int NewHealth)
{
//If health has changed of this object
if(this.GetInstanceID() != Enemy.GetInstanceID()) return;
Debug.Log ("Object: " + gameObject.name + " Health is: " + NewHealth.ToString());
}
//-------------------------------------------------------
}