1. 程式人生 > >Unity中的訊息機制

Unity中的訊息機制

在遊戲開發中,我們經常需要傳遞訊息。

傳遞訊息一般有三種方法:
1. 儲存物件的引用。
2. Unity 提供的 Message機制。
3. C#中的委託和事件。

儲存物件的引用

例如手榴彈爆炸的時候, 需要獲取手榴彈, 地面, 附近物體等遊戲元素的物件, 然後播放爆炸特效。
這種方法是簡單粗暴, 但是當專案的規模變大時, 增刪改查將會變的很麻煩。
其實這是一種耦合度較高的方案。

Unity 提供的 Message機制

Unity 本身提供了一種Messages訊息機制。

    • Calls the method named methodName on every MonoBehaviour in this game object or any of its children.
    • 對一個物體及其所有子物體,進行訊息的廣播,如果其中任何子物體上貼有指令碼,而指令碼中有相應的處理此訊息的函式,則Invoke呼叫。
    • BroadcastMessage 朝物體和所有子物體傳送訊息。
    • Calls the method named methodName on every MonoBehaviour in this game object.
    • 在遊戲物體每一個 MonoBehaviour 上呼叫名為methodName的方法。
    • SendMessage 朝本級別物體的多個指令碼傳送資訊,也就是向當前物件掛載的所有指令碼上面傳送訊息。 (父物體、子物體中所有MonoBehavior都不會接收到該訊息,即使包含methodName的方法)
    • Calls the method named methodName on every MonoBehaviour in this game object and on every ancestor of the behaviour.
    • 在遊戲物體每一個 MonoBehaviour 和每一個 behaviour 的祖先上呼叫名為methodName的方法。
    • SendMessageUpwards朝物體和上級父物體傳送資訊。

C#中的事件

C#中的委託和事件,對於訊息傳遞來說非常好用,從設計模式的角度上來說,是一個典型的觀察者模式。

例如我們實現一個搖桿, 可以在設計 RockerTouchBegin, RockerTouchMove, RockerTouchEnd 三個事件,

而對這個事件感興趣的物件會通過相應的 Handler 對該事件進行監聽,這樣就可以進行一對多的 GameObject 間的通訊了。

具體可以參考下面給出的實現。

public class Rocker : MonoBehaviour, IPointerDownHandler, IPointerUpHandler, IDragHandler {

    public delegate void RockerTouchBegin(Vector2 vec);
    public delegate void RockerTouchMove(Vector2 vec);
    public delegate void RockerTouchEnd();

    public event RockerTouchBegin OnTouchBegin;
    public event RockerTouchMove OnTouchMove;
    public event RockerTouchEnd OnTouchEnd;

    private bool isTouched = false;

    public void OnPointerDown(PointerEventData eventData) {
        isTouched = true;
        if (null != OnTouchBegin)
            OnTouchBegin(eventData.position);
    }

    public void OnPointerUp(PointerEventData eventData) {
        isTouched = false;
        if (null != OnTouchEnd)
            OnTouchEnd();
    }

    public void OnDrag(PointerEventData eventData) {
        if (null != OnTouchMove)
            OnTouchMove(eventData.position);
    }
}

private Rocker rocker;

void Start() {
    rocker = FindObjectOfType<Rocker>();
    rocker.OnTouchBegin += OnTouchBegin;
    rocker.OnTouchMove += OnTouchMove;
    rocker.OnTouchEnd += OnTouchEnd;
}

void OnTouchBegin(Vector2 vec) {
    Debug.Log("OnTouchBegin");
}

void OnTouchMove(Vector2 vec) {
    Debug.Log("OnTouchMove");
}

void OnTouchEnd() {
    Debug.Log("OnTouchEnd");
}

如有錯誤,歡迎指出。

email:dxmdxm1992#gmail.com