如何在Unity3D中使用C#事件

3

我已经使用Winforms很长时间了,对事件处理有一定的经验,但是在Unity开发方面还比较新手。我的项目只是想在Android上运行一些C#代码,所以没有必要使用超级高效的解决方案,只需要一个能工作的就可以。

事件处理程序声明:

public event EventHandler OnShow, OnHide, OnClose;

事件处理程序调用:

Debug.Log("OnShow");
if (OnShow != null) 
{
Debug.Log("OnShow_Firing");
OnShow(this, new EventArgs()); 
}
else{
Debug.Log("OnShow_empty");
}

在同一游戏对象中但另一个脚本中添加的事件处理程序。
void Awake(){
Debug.Log("Awake");
this.gameObject.GetComponent<windowScript>().OnShow += OnShowCalled;
}
private void OnShowCalled(object o,EventArgs e)
{
Debug.Log("OnShowCalled");
}

我的调试输出如下:

  1. "Awake"
  2. "OnShow"
  3. "OnShowFiring"

但是 "OnShowCalled" 没有被执行,Unity 的控制台中没有任何异常。 我尝试使用 EventArgs.Empty 而非评论中提到的 new EventArgs(),但对我的问题没有影响。

希望得到任何帮助。


我的猜测是你订阅的对象并非触发事件的对象。在日志中添加信息以帮助识别对象实例,或者在“Debug.Log(“OnShow”)”上添加断点,查看实际触发事件的对象是哪个。另外:使用EventArgs.Empty而不是new EventArgs() - Olivier Jacot-Descombes
场景中只有一个GameObject同时装备了这两个脚本,谢谢,我会尝试使用EventArgs.Empty - leAthlon
你的 this.gameObject.GetComponent<WindowScript>() 有点让我感到奇怪。有可能是因为你没有订阅调用 OnShow() 的对象吗? - Brandon
验证 Awake() 是否真的被调用了 - matt-dot-net
只有一个游戏对象,但您正在订阅此游戏对象的脚本组件的事件。 - Olivier Jacot-Descombes
3个回答

7

首先,请查看此教程:https://unity3d.com/learn/tutorials/topics/scripting/events

我建议使用事件行为(event Action),对于初学者来说更易使用。

示例:

包含事件的类:

public class EventContainer : MonoBehaviour
{
    public event Action<string> OnShow;
    public event Action<string,float> OnHide;
    public event Action<float> OnClose;

    void Show()
    {
        Debug.Log("Time to fire OnShow event");
        if(OnShow != null)
        {
            OnShow("This string will be received by listener as arg");
        }
    }

    void Hide()
    {
        Debug.Log("Time to fire OnHide event");
        if(OnHide != null)
        {
            OnHide ("This string will be received by listener as arg", Time.time);
        }
    }



    void Close()
    {
        Debug.Log("Time to fire OnClose event");
        if(OnClose!= null)
        {
            OnClose(Time.time); // passing float value.
        }
    }
}

负责处理 EventContainer 类事件的类:

public class Listener : MonoBehaviour
{
    public EventContainer containor; // may assign from inspector


    void Awake()
    {
        containor.OnShow += Containor_OnShow;
        containor.OnHide += Containor_OnHide;
        containor.OnClose += Containor_OnClose;
    }

    void Containor_OnShow (string obj)
    {
        Debug.Log("Args from Show : " + obj);
    }

    void Containor_OnHide (string arg1, float arg2)
    {
        Debug.Log("Args from Hide : " + arg1);
        Debug.Log("Container's Hide called at " + arg2);
    }

    void Containor_OnClose (float obj)
    {
        Debug.Log("Container Closed called at : " + obj);
    }

}

1
为了调试目的,给你的组件添加一个Tag属性。然后使用以下方式进行初始化:
var component = this.gameObject.GetComponent<windowScript>();
component.Tag = "foo";
component.OnShow += OnShowCalled;    

并更改日志记录

Debug.Log("OnShow: " + Tag);

你将会看到你是否正在处理相同的对象。


-2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接