C#內置的事件機制和Unity3D姻緣
最近因為項目,也因為一些其他事情而導致學習的停止,抽個空來記錄下C#內置的事件在Unity3D中的使用。
我需要讓一個物體對鼠標懸停做出事件的響應的情況下,我們通常會創建一個繼承MonoBehaviour的腳本然後掛到該物體上,然後為該腳本創建OnMouseOver方法,例如我們需要懸停來改變物體顏色,可能會這樣寫。
using UnityEngine; using System.Collections; public class ChangeColor : MonoBehaviour { void OnMouseOver() { transform.GetComponent<Renderer>().material.color = Color.red; } }
這樣就實現了我們需要的目的,但是,問題又來了,我們需要讓另外的對象響應該事件呢?
解決辦法是保持另外對象的腳本引用,然後在你的OnMouseOver方法中調用它。這樣做沒問題,但是不夠好。因為你需要一直保持另外一個對象的引用,如果想通知多個對象要保持多個引用。代碼會變得很亂。
還有一種方法是Messages 消息 。
使用SendMessage或SendMessageUpwards方法。看上去這是解決問題的最好辦法,但是這些方法存在嚴重的缺陷,以我的觀點,你應該盡量不去使用它們。
這些方法的語法並不靈活,你需要傳遞一個方法名字的字符串,這樣做很容易出錯。另外這些方法只能用在同一個對象的附屬關系中。換句話說你只能在下面幾種情況中調用SendMessage或SendMessageUpwards方法,這些方法的腳本被關聯到同一個GameObject中,或者被關聯到這個GameObject的祖先關系對象中。
幸運的是有一個更好的解決辦法,這就是C#內置的事件機制。
我們先來看一下如何在Unity3D中使用事件機制。
public class ChangeColor : MonoBehaviour {
public delegate void EventHandler(GameObject e);
public event EventHandler MouseOver;
void OnMouseOver()
{
if (MouseOver != null)
MouseOver(this.gameObject);
}
}
我們把該腳本掛的物體A,然後新建一個腳本。
public class ChangeColor1 : MonoBehaviour { private GameObject _gameObject; // Use this for initialization void Start () { [...] _gameObject.GetComponent<ChangeColor>().MouseOver += Listener; [...] } void Listener(GameObject g) {
Debug.Log("響應事件的物體是 " + this.gameObject.name);
Debug.Log("觸發事件的物體是 "+g.name);
}
}
這種方式比用消息更靈活,因為它可以被用在任何一個腳本中,而不僅僅在同一個對象附屬關系中。如果在整個應用中保持一個單例模式的對象,你就可以監聽任何從這個對象分發出來的事件。另外一個重要特點,同一個監聽方法可以響應不同對象的事件。通過傳遞事件源對象的引用作為參數,你總會知道哪個對象分發了事件。
C#內置的事件機制和Unity3D姻緣