在 Unity 中,物体之间的通信除了可以使用 SendMessage 系列方法之外,还可以通过 delegate(委托)来实现。相比 SendMessage 的字符串反射方式,基于委托的事件派发更高效,也更便于在编译期发现问题。

下面给出一对最小示例:EventDispatcher 负责定义并在合适时机触发事件,Listener 负责把自己的回调方法注册到该事件上。同一个委托可以挂载多个回调,触发时会依次调用。

Listener

监听者在 Start 中找到挂有 EventDispatcher 组件的目标对象,然后把 OnEvent 方法注册到其事件委托上。这里特意注册了两次,用来演示多播委托的叠加效果;如果改用 = 赋值,则会覆盖已有的回调列表。

Listener:
                using UnityEngine;
                using System.Collections;
                
                public class Listener : MonoBehaviour {
                
                	// Use this for initialization
                	void Start () {
                        EventDispatcher ev = GameObject.Find("Cube").GetComponent<EventDispatcher>();
                
                        ev.ev += OnEvent;//可装载多个delegate
                        ev.ev += OnEvent;
                       // ev.ev = OnEvent;
                
                	}
                	void OnEvent(GameObject obj)
                    {
                        Debug.Log(obj.ToString() + "123" );
                
                
                    }
                	// Update is called once per frame
                	void Update () {
                
                	}
                }

EventDispatcher

派发者通过 delegate 声明事件签名,并暴露一个 EventHandle 类型的字段 ev 供外部订阅。在 Start 阶段先判空,再把自身的 gameObject 作为参数触发事件,所有已注册的回调都会被调用。

EventDispatcher:
                using UnityEngine;
                using System.Collections;
                
                public class EventDispatcher : MonoBehaviour
                {
                    public delegate void EventHandle(GameObject obj);
                    public EventHandle ev;
                
                    // Use this for initialization
                    void Start()
                    {
                        if (ev!=null)
                        {
                            ev(this.gameObject);
                
                        }
                    }
                
                    // Update is called once per frame
                    void Update()
                    {
                
                    }
                }