首页 > 代码库 > C#内置的事件机制和Unity3D姻缘

C#内置的事件机制和Unity3D姻缘

最近因为项目,也因为一些其他事情而导致学习的停止,抽个空来记录下C#内置的事件在Unity3D中的使用。

 

我需要让一个物体对鼠标悬停做出事件的响应的情况下,我们通常会创建一个继承MonoBehaviour的脚本然后挂到该物体上,然后为该脚本创建OnMouseOver方法,例如我们需要悬停来改变物体颜色,可能会这样写。

using UnityEngine;
using System.Collections;

public class ChangeColor : MonoBehaviour {

    void onm ouseOver()
    {
        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 onm ouseOver()
{
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姻缘