工具類——EventManager

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());
	}
	//-------------------------------------------------------
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章