【unity】ngui事件系統實現參考

http://blog.csdn.net/abcdtty/article/details/13021237html

事件系統是個好東西,不只調用方便,並且能最大程度的下降系統各部分的耦合度. 網上有關這方面的東西不少不少,我也用過很多,最近發現一個比較優秀的,即快速(不用遍歷大串的方法列表)又簡潔(代碼不多). 分享上來和新手同窗們共勉.ide

 

具體實現以下:this


1.先定義事件參數類: EventArgs 是基類,不建議直接使用,由於通用的東西針對性不強,容易混亂(特別是找bug 的時候)... MyEvent 的具體的派生類,建議的使用方法就是每一個種類的事件派生一個類,好比UIEvent,ServerEvent神馬的,根據具體做用來命名.spa

 

[csharp] view plaincopyprint?.net

  1. /// <summary>  orm

  2. /// 事件參數基類  htm

  3. /// </summary>  blog

  4. public class EventArgs  事件

  5. {  ip

  6.     public object Parameter;  

  7. }  

  8.   

  9. /// <summary>  

  10. /// 自定義事件參數  

  11. /// </summary>  

  12. public class MyEvent : EventArgs  

  13. {  

  14.     public int ID;  

  15.     public string Name; // ...etc   

  16. }  

    /// <summary>
    /// 事件參數基類
    /// </summary>
    public class EventArgs
    {
        public object Parameter;
    }

    /// <summary>
    /// 自定義事件參數
    /// </summary>
    public class MyEvent : EventArgs
    {
        public int ID;
        public string Name; // ...etc 
    }

 


2. 事件管理類: 能夠看出是一個單例類,世界各地都能直接調用. _delegates負責保存全部事件接收方法,事件被按類型存在裏面,同一個類型不管幾條記錄都只佔一個項(因此不用遍歷大串的方法列表)

 

[csharp] view plaincopyprint?

  1. /// <summary>  

  2. /// 事件管理類  

  3. /// </summary>  

  4. public class EventManager  

  5. {  

  6.     //單例模式.  

  7.     public static readonly EventManager Instance = new EventManager();  

  8.     private EventManager() { }  

  9.   

  10.     //事件委託.  

  11.     public delegate void EventDelegate<T>(T e) where T : EventArgs;  

  12.   

  13.     //保存全部事件<span style="font-family: Arial,Helvetica,sans-serif;">接收方法</span>.  

  14.     readonly Dictionary<Type, Delegate> _delegates = new Dictionary<Type, Delegate>();  

  15.   

  16.     //添加一個事件接收方法.  

  17.     public void AddListener<T>(EventDelegate<T> listener) where T : EventArgs  

  18.     {  

  19.         Delegate d;  

  20.         if (_delegates.TryGetValue(typeof(T), out d))  

  21.         {  

  22.             _delegates[typeof(T)] = Delegate.Combine(d, listener);  

  23.         }  

  24.         else  

  25.         {  

  26.             _delegates[typeof(T)] = listener;  

  27.         }  

  28.     }  

  29.   

  30.     //刪除一個事件接受方法  

  31.     public void RemoveListener<T>(EventDelegate<T> listener) where T : EventArgs  

  32.     {  

  33.         Delegate d;  

  34.         if (_delegates.TryGetValue(typeof(T), out d))  

  35.         {  

  36.             Delegate currentDel = Delegate.Remove(d, listener);  

  37.   

  38.             if (currentDel == null)  

  39.             {  

  40.                 _delegates.Remove(typeof(T));  

  41.             }  

  42.             else  

  43.             {  

  44.                 _delegates[typeof(T)] = currentDel;  

  45.             }  

  46.         }  

  47.     }  

  48.   

  49.     //發送事件.  

  50.     public void Send<T>(T e) where T : EventArgs  

  51.     {  

  52.         if (e == null)  

  53.         {  

  54.             throw new ArgumentNullException("e");  

  55.         }  

  56.   

  57.         Delegate d;  

  58.         if (_delegates.TryGetValue(typeof(T), out d))  

  59.         {  

  60.             EventDelegate<T> callback = d as EventDelegate<T>;  

  61.             if (callback != null)  

  62.             {  

  63.                 callback(e);  

  64.             }  

  65.         }  

  66.     }  

  67. }  

    /// <summary>
    /// 事件管理類
    /// </summary>
    public class EventManager
    {
        //單例模式.
        public static readonly EventManager Instance = new EventManager();
        private EventManager() { }

        //事件委託.
        public delegate void EventDelegate<T>(T e) where T : EventArgs;

        //保存全部事件接收方法.
        readonly Dictionary<Type, Delegate> _delegates = new Dictionary<Type, Delegate>();

        //添加一個事件接收方法.
        public void AddListener<T>(EventDelegate<T> listener) where T : EventArgs
        {
            Delegate d;
            if (_delegates.TryGetValue(typeof(T), out d))
            {
                _delegates[typeof(T)] = Delegate.Combine(d, listener);
            }
            else
            {
                _delegates[typeof(T)] = listener;
            }
        }

        //刪除一個事件接受方法
        public void RemoveListener<T>(EventDelegate<T> listener) where T : EventArgs
        {
            Delegate d;
            if (_delegates.TryGetValue(typeof(T), out d))
            {
                Delegate currentDel = Delegate.Remove(d, listener);

                if (currentDel == null)
                {
                    _delegates.Remove(typeof(T));
                }
                else
                {
                    _delegates[typeof(T)] = currentDel;
                }
            }
        }

        //發送事件.
        public void Send<T>(T e) where T : EventArgs
        {
            if (e == null)
            {
                throw new ArgumentNullException("e");
            }

            Delegate d;
            if (_delegates.TryGetValue(typeof(T), out d))
            {
                EventDelegate<T> callback = d as EventDelegate<T>;
                if (callback != null)
                {
                    callback(e);
                }
            }
        }
    }

3. 使用示例: 使用灰常簡單,以下: 先添加一個事件接收方法(就是當事件被髮出的時候會調用的接收方法), 而後須要觸發事件時使用Send方法發送便可.

 

[csharp] view plaincopyprint?

  1. /// <summary>  

  2. /// 使用示例  

  3. /// </summary>  

  4. public class Test  

  5. {  

  6.     public Test()  

  7.     {  

  8.         //添加事件接收方法  

  9.         EventManager.Instance.AddListener<MyEvent>(ReceiveEvent);  

  10.   

  11.   

  12.         //發送MyEvent事件, 以後ReceiveEvent(MyEvent e)方法將被調用.  

  13.         MyEvent e = new MyEvent(); //事件參數.  

  14.         e.ID =0;  

  15.         e.Name = "XOXOOX";  

  16.         //事件發送  

  17.         EventManager.Instance.Send<MyEvent>(e);  

  18.     }  

  19.   

  20.     //接收MyEvent事件的方法.  

  21.     public void ReceiveEvent(MyEvent e)  

  22.     {  

  23.           

  24.     }  

  25.   

  26. }  

 

    /// <summary>
    /// 使用示例
    /// </summary>
    public class Test
    {
        public Test()
        {
            //添加事件接收方法
            EventManager.Instance.AddListener<MyEvent>(ReceiveEvent);


            //發送MyEvent事件, 以後ReceiveEvent(MyEvent e)方法將被調用.
            MyEvent e = new MyEvent(); //事件參數.
            e.ID =0;
            e.Name = "XOXOOX";
            //事件發送
            EventManager.Instance.Send<MyEvent>(e);
        }

        //接收MyEvent事件的方法.
        public void ReceiveEvent(MyEvent e)
        {
            
        }

    }

http://www.xuebuyuan.com/1562272.html

窗體有三種:幾秒後消失的,按肯定後消失的,選擇是或者否而後消失的

 

一個比較簡單高效的事件系統,
EventManager.Instance.AddListener<UINotificaionArgs>(CallNotification);//註冊事件
//觸發彈窗的方法
EventManager.Instance.Send(new UINotificationArgs(){NMessageType = NMessageType.AskForYesOrNot,del = 你要執行的方法 ,Infomation  = 你要顯示的信息});//這個是帶有按下肯定後執行相應方法的彈窗
EventManager.Instance.Send(new UINotificationArgs(){NMessageType = NMessageType.AskForOk,Infomation  = 你要顯示的信息});//這個是沒有方法,但要你按下確認纔會消失的彈窗
EventManager.Instance.Send(new UINotificationArgs(){NMessageType = NMessageType.NoAsk,Infomation  = 你要顯示的信息,WaitTime = 4f});//這個是沒有按鈕,可是會在幾秒後彈窗消失的模式

//理解了這個事件系統就容易理解原理了
//至於具體的NGUI實現,看下面的變量名稱也大約能明白了,工程無法上傳

 

 

using UnityEngine;
using System.Collections;

public class UINotificaionArgs : EventArgs {
	private NMessageType nMessageType;
	public NMessageType NMessageType {
		get {
			return nMessageType;
		}
		set {
			nMessageType = value;
		}
	}
	private string infomation;
	public string Infomation {
				get {
						return infomation;
				}
				set {
						infomation = value;
				}
		}
	private float  waitTime;
	public float WaitTime {
		get {
			return waitTime;
		}
		set {
			waitTime = value;
		}
	}


	//public  delegate void NotificationDel();
	public DelegateManage.NotificationDel del;
}



public  class DelegateManage
{
	public  delegate void NotificationDel();
}

public enum NMessageType
{
	NoAsk,
	AskForOk,
	AskForYesOrNot

}

 

 

以上是事件的內容部分,傳遞三個參數,一個是彈窗的類型,一個是須要等待的時間(第一種窗體須要),一個按下肯定後執行的方法的委託

 

下面的是彈窗的具體管理組件

首先註冊事件

而後是根據傳遞來的事件的具體內容,執行相關的方法

最後的兩個方法是爲按鈕準備的

按下yes以後執行pressOk()

就調用了經過事件傳遞的,按下肯定後,須要執行的方法了

 

using UnityEngine;
using System.Collections;

public class NotifacationManager : MonoBehaviour {
	public UILabel  Info;
	public GameObject Ask;
	public GameObject AskOrNot;
	private NMessageType messageType;
	private float WaitTime;
	private DelegateManage.NotificationDel del;


	void Start()
	{
		EventManager.Instance.AddListener<UINotificaionArgs>(CallNotification);

	}

	public void DisplayWindow()
	{
		foreach (Transform child in this.transform) {
			child.gameObject.SetActive(true);
				}
	}

	public void HideWindow()
	{
		foreach (Transform child in this.transform) {
			child.gameObject.SetActive(false);
		}
	}

	private void CallNotification(UINotificaionArgs e)
	{
		DisplayWindow ();
		Info.text = e.Infomation;
		switch (e.NMessageType) 
		{
		case NMessageType.NoAsk:
			WaitTime = e.WaitTime;
			StartCoroutine(NoAsk());
			break;
		case NMessageType.AskForOk:
			del = e.del;
			AskForOk();
			break;
		case NMessageType.AskForYesOrNot:
			del = e.del;
			AskOkOrNot();
			break;
		}
	}

	IEnumerator  NoAsk()
	{
		Ask.SetActive (false);
		AskOrNot.SetActive (false);
		yield return new WaitForSeconds(WaitTime);
		HideWindow ();
	}
	void  AskForOk()
	{
		Ask.SetActive (true);
		AskOrNot.SetActive (false);
	}
	void  AskOkOrNot()
	{
		Ask.SetActive (false);
		AskOrNot.SetActive (true);
	}


	public void PressOK()
	{
		del ();
		HideWindow ();
	}

	public void PressNo()
	{
		HideWindow ();
	}

}
相關文章
相關標籤/搜索