乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      C# 事件和Unity3D

       阿修羅之獅猿授 2016-03-29
           翻譯自:
      http://www./blog/index.php/2010/10/04/c-events-and-unity3d/

      zijan譯

      (括號內(nèi)是譯者自己對文章和技術(shù)的理解)
      (Unity3D是現(xiàn)在越來越流行的3D游戲引擎,它支持JavaScript,c#和Boo語言。如果你是個Unity3D的愛好者,但只會JavaScript。這里有一篇文章關(guān)于處理事件和消息傳遞,也許更適合你。A Useful Messaging System

      你知道C#有一個內(nèi)置的事件機制嗎?這個東東在Unity3D里也非常好用。下面舉一個例子。

      為了響應(yīng)一個GameObject的事件分發(fā),你通常要建立一個腳本繼承MonoBehaviour并且實現(xiàn)你需要的方法。比如你想對鼠標懸停作出反應(yīng),就要創(chuàng)建OnMouseOver方法。通常代碼會像這個樣子:

      C#代碼  收藏代碼
      1. void OnMouseOver () {  
      2.   renderer.material.color = Color.red;  
      3. }  



      這樣工作沒問題。但如果你想通知另外一個對象響應(yīng)這個事件(OnMouseOver事件)怎么辦?

      第一種方式是保持另外對象的腳本引用,然后在你的OnMouseOver方法中調(diào)用它:

      C#代碼  收藏代碼
      1. public MyScript myScript;  
      2. void OnMouseOver () {  
      3.   myScript.NotifyMouseOver();  
      4. }  



      這樣做沒問題,但是不夠好。因為你需要一直保持另外一個對象的引用,如果想通知多個對象要保持多個引用。代碼會變得很亂。

      Messages 消息

      另一個辦法是用SendMessage或SendMessageUpwards方法??瓷先ミ@是解決問題的最好辦法,但是這些方法存在嚴重的缺陷,以我的觀點,你應(yīng)該盡量不去使用它們。

      這些方法的語法并不靈活,你需要傳遞一個方法名字的字符串,這樣做很容易出錯。另外這些方法只能用在同一個對象的附屬關(guān)系中。換句話說你只能在下面幾種情況中調(diào)用SendMessage或SendMessageUpwards方法,這些方法的腳本被關(guān)聯(lián)到同一個GameObject中,或者被關(guān)聯(lián)到這個GameObject的祖先關(guān)系對象中。

      Events 事件

      幸運的是有一個更好的解決辦法,這就是C#內(nèi)置的事件機制。我不在這里過多的描述機制是如何工作的,你如果有興趣可以學(xué)習(xí)相關(guān)的知識,訪問MSDN手冊。(譯者推薦另外一篇文章,C# 中的委托和事件

      現(xiàn)在讓我們看看如何在Unity3D中使用事件機制。

      C#代碼  收藏代碼
      1. using UnityEngine;  
      2. public class EventDispatcher : MonoBehaviour {  
      3.   public delegate void EventHandler(GameObject e);  
      4.   public event EventHandler MouseOver;  
      5.   void OnMouseOver () {  
      6.     if (MouseOver != null)  
      7.         MouseOver (this.gameObject);  
      8.   }  
      9. }  


      如果你不知道這段代碼到底干什么,先不要著急。重要的是一旦你把這段代碼關(guān)聯(lián)到一個GameObject,只要在整個項目的任何一個腳本中保持這個對象,你就可以像下面這樣處理事件:

      C#代碼  收藏代碼
      1. private GameObject s;  
      2. [...]  
      3. s.GetComponent<EventDispatcher>().MouseOver += Listener;  
      4. [...]  
      5. void Listener(GameObject g) {  
      6.    // g is being hovered, do something...  
      7. }  


      這種方式比用消息更靈活,因為它可以被用在任何一個腳本中,而不僅僅在同一個對象附屬關(guān)系中。如果在整個應(yīng)用中保持一個單例模式的對象,你就可以監(jiān)聽任何從這個對象分發(fā)出來的事件。

      另外一個重要特點,同一個監(jiān)聽方法可以響應(yīng)不同對象的事件。通過傳遞事件源對象的引用作為參數(shù),你總會知道哪個對象分發(fā)了事件,就像我的代碼展示的那樣。(對于這句話可以這樣理解,假如游戲中扔一顆導(dǎo)彈炸死了一個小兵并導(dǎo)致坦克減血,小兵死亡和坦克減血這兩個事件都觸發(fā)了同一個監(jiān)聽方法-玩家得分,通過傳遞進來的事件源對象,就能知道小兵還是坦克觸發(fā)了玩家得分這個監(jiān)聽方法。)

      References, controllers and MVC

      現(xiàn)在讓我們比較一下第一和第三種方式。在最開始的例子中(第一種方式保持另外對象的腳本引用),你需要在事件分發(fā)代碼中保持監(jiān)聽者的對象引用,我說了這不是一個好主意。在用內(nèi)置事件機制,改進的版本中(第三種方式),你需要在監(jiān)聽者代碼中保持事件分發(fā)者的引用。你也許會問,為什么后者更好?

      首先,分發(fā)者不需要知道自己事件的監(jiān)聽者是誰,不需要知道有多少監(jiān)聽者。它只負責(zé)事件的發(fā)送。在最開始的例子中(第一種方式),如果要告訴分發(fā)者停止通知監(jiān)聽者,你能想象這種程序判斷有多么笨重嗎?

      事件機制中,是由監(jiān)聽者自己決定監(jiān)聽什么事件,什么時候開始監(jiān)聽,什么時候停止監(jiān)聽。像這樣的對象通常用于管理程序的狀態(tài)或者執(zhí)行某些游戲邏輯。這個就叫做控制器,借用MVC設(shè)計模式的概念。這樣我們的代碼會更清晰,不易出錯。(譯者認為觀察者設(shè)計模式更符合)

      最后一點,我喜歡重載“+=”操作符去添加監(jiān)聽方法?,F(xiàn)在你也許能夠猜到,如果想結(jié)束監(jiān)聽某個事件,可以這么寫:

      C#代碼  收藏代碼
      1. s.GetComponent<EventDispatcher>().MouseOver -= Listener;  


      當然你可以創(chuàng)建一個通用的EventDispatcher類,實現(xiàn)所有GameObject能夠分發(fā)的事件??梢詤⒖聪旅娴拇a。另外在實現(xiàn)OnGUI事件時要特別小心,如果想知道為什么,讀讀這篇文章。

      C#代碼  收藏代碼
      1. using UnityEngine;  
      2. using System.Collections;  
      3.   
      4. /**  
      5.  *  A simple event dispatcher - allows to listen to events in one GameObject from another GameObject 
      6.  * 
      7.  *  Author: Bartek Drozdz (bartek [at] everyday3d [dot] com) 
      8.  * 
      9.  *  Usage: 
      10.  *  Add this script to the object that is supposed to dispatch events.  
      11.  *  In another objects follow this pattern to register as listener at intercept events: 
      12.   
      13.     void Start () { 
      14.         EventDispatcher ev = GameObject.Find("someObject").GetComponent<EventDispatcher>(); 
      15.         ev.MouseDown += ListeningFunction; // Register the listener (and experience the beauty of overloaded operators!) 
      16.     } 
      17.  
      18.     void ListeningFunction (GameObject e) { 
      19.         e.transform.Rotate(20, 0, 0); // 'e' is the game object that dispatched the event 
      20.         e.GetComponent<EventDispatcher>().MouseDown -= ListeningFunction; // Remove the listener 
      21.     } 
      22.      
      23.  *  This class does not implement all standards events, nor does it allow dispatching custom events,  
      24.  *  but you shold have no problem adding all the other methods. 
      25.  */  
      26. public class EventDispatcher : MonoBehaviour  
      27. {  
      28.   
      29.     public delegate void EventHandler (GameObject e);  
      30.     public delegate void CollisionHandler (GameObject e, Collision c);  
      31.   
      32.     public event EventHandler MouseOver;  
      33.     void OnMouseOver ()  
      34.     {  
      35.         if (MouseOver != null)  
      36.             MouseOver (this.gameObject);  
      37.     }  
      38.   
      39.     public event EventHandler MouseDown;  
      40.     void OnMouseDown ()  
      41.     {  
      42.         if (MouseDown != null)  
      43.             MouseDown (this.gameObject);  
      44.     }  
      45.   
      46.     public event EventHandler MouseEnter;  
      47.     void OnMouseEnter ()  
      48.     {  
      49.         if (MouseEnter != null)  
      50.             MouseEnter (this.gameObject);  
      51.     }  
      52.   
      53.   
      54.     public event EventHandler MouseExit;  
      55.     void OnMouseExit ()  
      56.     {  
      57.         if (MouseExit != null)  
      58.             MouseExit (this.gameObject);  
      59.     }  
      60.   
      61.     public event EventHandler BecameVisible;  
      62.     void OnBecameVisible ()  
      63.     {  
      64.         if (BecameVisible != null)  
      65.             BecameVisible (this.gameObject);  
      66.     }  
      67.   
      68.     public event EventHandler BecameInvisible;  
      69.     void OnBecameInvisible ()  
      70.     {  
      71.         if (BecameInvisible != null)  
      72.             BecameInvisible (this.gameObject);  
      73.     }  
      74.   
      75.     public event CollisionHandler CollisionEnter;  
      76.     void OnCollisionEnter (Collision c)  
      77.     {  
      78.         if (CollisionEnter != null)  
      79.             CollisionEnter (this.gameObject, c);  
      80.     }  
      81.   
      82.     public event CollisionHandler CollisionExit;  
      83.     void OnCollisionExit (Collision c)  
      84.     {  
      85.         if (CollisionExit != null)  
      86.             CollisionExit (this.gameObject, c);  
      87.     }  
      88.       
      89. }  

        本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
        轉(zhuǎn)藏 分享 獻花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多