1. 程式人生 > >關於Unity的委託事件處理指令碼之間的互動

關於Unity的委託事件處理指令碼之間的互動

這裡可能需要前期準備一下c#的委託(delegate)和事件(event)方面的知識了。。。
不是很明白的,就各種谷歌吧~
需要準備二個繼承與MonoBehaviour的EventDispatcher類和EventListener類。
我這裡吧delegate就寫在EventDispatcher裡了,也可以新建一個類吧這些delegate存在裡面,方便一點。。。
  1. //定義委託事件,它定義了可以代表的方法的型別
  2.         /**事件*/
  3.         public delegate void EventHandler(GameObject e); 
  4.         /**碰撞檢測*/
  5.         public delegate void CollisionHandler(GameObject e,Collision c);
  6.         /**觸發器檢測*/
  7. public delegate void TriggerHandler(GameObject e,Collider other);
  8.         /**控制器碰撞檢測*/
  9.         public delegate void ControllerColliderHitHandler(GameObject e,ControllerColliderHit hit);
  10.         /**新關卡被載入進來*/
  11.         public delegate void LevelWasLoadedHandler(GameObject e,int level);
複製程式碼 委託定義好了,其實這些就類似於方法引數一樣。。。可意會不好言傳啊。。。


然後重寫MonoBehaviour支援的那些時間響應函式:
比如OnMouseDown();
首先定義一個EventHandler 這個委託的事件。。。然後再OnMouseDown響應函式裡對他進行操作。。
如果某個GameObject偵聽了這個事件並寫出了響應函式(響應函式即是定義事件的委託delegate),那麼在重寫的OnMouseDown函式類就會呼叫執行這個傳進來的delegate並且把this.gameObject傳出去。
  1. public event EventHandler MouseDown; 
  2.         void OnMouseDown(){ 
  3.                 if (MouseDown != null) 
  4.                         MouseDown (this.gameObject);
  5.         }
複製程式碼

以此類推,附上EventDispatcher類:
  1. using System;
  2. using UnityEngine; 
  3. /** 
  4. *  基於MonoBehaviour的一個事件派發類
  5. * A simple event dispatcher - allows to listen to events in one GameObject from another GameObject
  6. *
  7. *
  8. *  Usage:
  9. *  Add this script to the object that is supposed to dispatch events. 
  10. *  In another objects follow this pattern to register as listener at intercept events:
  11.     void Start () {
  12.         EventDispatcher ev = GameObject.Find("someObject").GetComponent<EventDispatcher>();
  13.         ev.MouseDown += ListeningFunction; // Register the listener (and experience the beauty of overloaded operators!)
  14.     }
  15.     void ListeningFunction (GameObject e) {
  16.         e.transform.Rotate(20, 0, 0); // 'e' is the game object that dispatched the event
  17.         e.GetComponent<EventDispatcher>().MouseDown -= ListeningFunction; // Remove the listener
  18.     }
  19. *  This class does not implement all standards events, nor does it allow dispatching custom events, 
  20. *  but you shold have no problem adding all the other methods.
  21. *
  22. * date: 2013.8.21
  23. */ 
  24. public class EventDispatcher:MonoBehaviour{
  25.         //定義委託事件,它定義了可以代表的方法的型別
  26.         /**事件*/
  27.         public delegate void EventHandler(GameObject e); 
  28.         /**碰撞檢測*/
  29.         public delegate void CollisionHandler(GameObject e,Collision c);
  30.         /**觸發器檢測*/
  31.         public delegate void TriggerHandler(GameObject e,Collider other);
  32.         /**控制器碰撞檢測*/
  33.         public delegate void ControllerColliderHitHandler(GameObject e,ControllerColliderHit hit);
  34.         /**新關卡被載入進來*/
  35.         public delegate void LevelWasLoadedHandler(GameObject e,int level);
  36.         public event EventHandler MouseEnter; 
  37.         void OnMouseEnter(){ 
  38.                 if (MouseEnter != null)  //如果有方法註冊委託變數
  39.                         MouseEnter(this.gameObject); //通過委託呼叫方法
  40.         }
  41.         public event EventHandler MouseOver;
  42.         void OnMouseOver(){ 
  43.                 if (MouseOver != null) 
  44.                         MouseOver (this.gameObject);
  45.         }
  46.         public event EventHandler MouseExit; 
  47.         void OnMouseExit(){ 
  48.                 if (MouseExit != null) 
  49.                         MouseExit (this.gameObject);
  50.         }
  51.         public event EventHandler MouseDown; 
  52.         void OnMouseDown(){ 
  53.                 if (MouseDown != null) 
  54.                         MouseDown (this.gameObject);
  55.         }
  56.         public event EventHandler MouseUp; 
  57.         void OnMouseUp(){ 
  58.                 if (MouseUp != null) 
  59.                         MouseUp (this.gameObject);
  60.         }
  61.         public event EventHandler MouseDrag; 
  62.         void OnMouseDrag(){ 
  63.                 if (MouseDrag != null) 
  64.                         MouseDrag (this.gameObject);
  65.         }
  66.         /**當renderer(渲染器)在任何相機上可見時呼叫OnBecameVisible*/
  67.         public event EventHandler BecameVisible; 
  68.         void OnBecameVisible (){ 
  69.                 if (BecameVisible != null) 
  70.                         BecameVisible (this.gameObject); 
  71.         } 
  72.         /**當renderer(渲染器)在任何相機上都不可見時呼叫OnBecameInvisible*/
  73.         public event EventHandler BecameInvisible; 
  74.         void OnBecameInvisible (){ 
  75.                 if (BecameInvisible != null) 
  76.                         BecameInvisible (this.gameObject); 
  77.         } 
  78.         public event EventHandler Enable;
  79.         void OnEnable(){
  80.                 if(Enable != null)
  81.                         Enable(this.gameObject);
  82.         }
  83.         public event EventHandler Disable;
  84.         void OnDisable(){
  85.                 if(Disable != null)       
  86.                         Disable(this.gameObject);
  87.         }
  88.          public event EventHandler Destroy;
  89.         void OnDestroy(){
  90.                 if(Destroy != null)
  91.                         Destroy(this.gameObject);
  92.         }
  93.         /**在相機渲染場景之前呼叫*/
  94.         public event EventHandler PreRender;
  95.         void OnPreRender(){
  96.                 if(PreRender != null)
  97.                         PreRender(this.gameObject);
  98.         }
  99.         /**在相機完成場景渲染之後呼叫*/
  100.         public event EventHandler PostRender;
  101.         void OnPostRender(){
  102.                 if(PostRender != null)
  103.                         PostRender(this.gameObject);
  104.         }
  105.         /**在相機場景渲染完成後被呼叫*/
  106.         public event EventHandler RenderObject;
  107.         void OnRenderObject(){
  108.                 if(RenderObject != null)
  109.                         RenderObject(this.gameObject);
  110.         }
  111.         public event EventHandler ApplicationPause;
  112.         void OnApplicationPause(){
  113.                 if(ApplicationPause != null)
  114.                         ApplicationPause(this.gameObject);
  115.         }
  116.         /**當玩家獲得或失去焦點時傳送給所有遊戲物體*/
  117.         public event EventHandler ApplicationFocus;
  118.         void OnApplicationFocus(){
  119.                 if(ApplicationFocus != null)
  120.                         ApplicationFocus(this.gameObject);
  121.         }
  122.         public event EventHandler ApplicationQuit;
  123.         void OnApplicationQuit(){
  124.                 if(ApplicationQuit != null)
  125.                         ApplicationQuit(this.gameObject);
  126.         }
  127.         public event TriggerHandler TriggerEnter;
  128.         void OnTriggerEnter(Collider other){
  129.                 if(TriggerEnter != null)
  130.                         TriggerEnter(this.gameObject,other);
  131.         }
  132.         public event TriggerHandler TriggerExit;
  133.         void OnTriggerExit(Collider other){
  134.                 if(TriggerExit != null)
  135.                         TriggerExit(this.gameObject,other);
  136.         }
  137.         public event TriggerHandler TriggerStay;
  138.         void OnTriggerStay(Collider other){
  139.                 if(TriggerStay != null)
  140.                         TriggerStay(this.gameObject,other);
  141.         }
  142.         public event ControllerColliderHitHandler controllerColliderHit;
  143.           void OnControllerColliderHit(ControllerColliderHit hit){
  144.                 if(controllerColliderHit != null)
  145.                         controllerColliderHit(this.gameObject,hit);
  146.         }
  147.     public event CollisionHandler CollisionEnter; 
  148.     void OnCollisionEnter (Collision c){ 
  149.         if (CollisionEnter != null) 
  150.             CollisionEnter (this.gameObject, c); 
  151.     } 
  152.          public event CollisionHandler CollisionStay; 
  153.     void OnCollisionStay (Collision c){ 
  154.         if (CollisionStay != null) 
  155.             CollisionStay (this.gameObject, c); 
  156.     } 
  157.     public event CollisionHandler CollisionExit; 
  158.     void OnCollisionExit (Collision c){ 
  159.         if (CollisionExit != null) 
  160.             CollisionExit (this.gameObject, c); 
  161.     }
  162.         public event LevelWasLoadedHandler LevelWasLoaded;
  163.         void OnLevelWasLoaded(int level){
  164.                 if(LevelWasLoaded != null)
  165.                         LevelWasLoaded(this.gameObject,level);
  166.         }
複製程式碼 寫好了派發事件的類拖到需要派發事件出來的元件上,然後再來註冊和偵聽吧,下面寫出EventListener類做出偵聽的步驟。。
首先需要獲取目標元件上的EventDispatcher元件。
  1. private EventDispatcher evt = null;
  2.         // Use this for initialization
  3.         void Start () {
  4.                 evt = GameObject.Find("Cube1").GetComponent<EventDispatcher>();
  5.         }
複製程式碼 獲取到目標物件後,就要將本地的響應函式,新增到EventDispatcher 的事件 委託裡去。
  1. /**註冊偵聽器函式*/
  2.         void addEventListener(){
  3.                 //給委託的事件型別變數賦值
  4.                 evt.MouseDown +=OnMouseDownListener;
  5.                 evt.MouseDrag += OnMouseDragLIstener;
  6.         }
複製程式碼 evt.MouseDown 可以簡單的理解成一個delegate,+= 將本地函式(delegate規定的型別和引數)賦值進去,當然瞭解除監聽就用 -= 啦~~

完了再寫出處理函式。。。
  1. /**事件響應處理函式
  2.          * @param GameObject e 事件源的GameObject物件
  3.          * <li> 事件響應函式的引數,參見EventDispatcher類中的相應事件Handler的引數個數
  4.          * */
  5.         void OnMouseDownListener(GameObject e){
  6.                 print("on mouse down..");
  7.                 e.transform.Rotate(20, 0, 0);
  8.                 //移除偵聽函式
  9.                 e.GetComponent<EventDispatcher>().MouseDown -= OnMouseDownListener;
  10.         }
  11.         void OnMouseDragLIstener(GameObject e){
  12.                 print("on mouse drag..");
  13.         }
複製程式碼

附上EventListener原始碼:
  1. using UnityEngine;
  2. using System.Collections;
  3. /**
  4. * 響應事件
  5. * */
  6. public class EventListener : MonoBehaviour {
  7.         private EventDispatcher evt = null;
  8.         // Use this for initialization
  9.         void Start () {
  10.                 evt = GameObject.Find("Cube1").GetComponent<EventDispatcher>();
  11.                 addEventListener();
  12.         }
  13.         /**註冊偵聽器函式*/
  14.         void addEventListener(){
  15.                 //給委託的事件型別變數賦值
  16.                 evt.MouseDown +=OnMouseDownListener;
  17.                 evt.MouseDrag += OnMouseDragLIstener;
  18.         }
  19.         // Update is called once per frame
  20.         void Update () {
  21.         }
  22.         /**事件響應處理函式
  23.          * @param GameObject e 事件源的GameObject物件
  24.          * <li> 事件響應函式的引數,參見EventDispatcher類中的相應事件Handler的引數個數
  25.          * */
  26.         void OnMouseDownListener(GameObject e){
  27.                 print("on mouse down..");
  28.                 e.transform.Rotate(20, 0, 0);
  29.                 //移除偵聽函式
  30.                 //e.GetComponent<EventDispatcher>().MouseDown -= OnMouseDownListener;
  31.         }
  32.         void OnMouseDragLIstener(GameObject e){
  33.                 print("on mouse drag..");
  34.         }
  35. }
複製程式碼 。。程式碼碼玩了,繫結到響應的Cube上去試試吧~~~


5.png
完成了。。。


有問題,大家一起研究,一起學習,一起進步~~