繁体   English   中英

Unity 中的简单事件系统

[英]Simple event system in Unity

我正在尝试在 Unity 中使用事件系统(C# 方式),但是我在实现它时遇到了问题。

大多数示例都显示了一个类,您可以在其中定义处理程序; 然后在同一个类中编写与处理程序签名匹配的函数,并将事件编写为静态

public class EventExample : MonoBehaviour
{
    public delegate void ExampleEventHandler();
    public static event ExampleEventHandler OneDayPassed;

    public static void NextTurn()
    {
        // do stuff then send event
        if (OneDayPassed != null)
            OneDayPassed();
    }
}

然后在另一个类中,您订阅事件,创建一个实际执行某些操作的函数

public class EntityWatcher: MonoBehaviour
{
    void Start()
    {
        EventExample.OneDayPassed += this.PrepareNextDay;
    }

    public void PrepareNextDay()
    {
        // Do other stuff that happen after the day is done

    }
}

到目前为止没有问题,但我不确定如何设计它,因此任何特定类型的 GameObject 都会订阅此事件。 例如,如果您有一个 GO 的人员类别,即 8 到 6 人工作,并且您在运行时实例化它们; 我应该订阅这个类别的主类,还是应该创建一个附加到游戏对象预制件的脚本来订阅事件?

目标是所有应该在体育中心进行 8 到 6 班轮班的工作人员都知道“一天结束”事件何时开始,但我不想订阅我实例化的每个预制件。

根据我的理解,我应该在预制件上附加一个带有所需代码的脚本,但我找不到一个实际的例子来说明这是否真的是这样做的方法。

您必须使用UnityEvent

public UnityEvent whoa;

这很容易。

制作脚本 BigScript.cs

using UnityEngine;
using System.Collections;
using UnityEngine.Events;

public class BigScript:MonoBehaviour
{
    [Header("Here's a cool event! Drag anything here!")]
    public UnityEvent whoa;
}

把它放在一个游戏对象上。 现在在 Inspector 中查看它

您将看到“哇”事件。

只需将您的其他脚本拖到那里,当“哇”发生时,在那些其他脚本上发生一些事情。

在此处输入图片说明

就这么简单。 要在 BigScript 中调用事件,只需

    [Header("Here's a cool event! Drag anything here!")]
    public UnityEvent whoa;
    
    private void YourFunction()
    {
        whoa.Invoke();
    }

在极少数情况下,您可能需要通过代码添加侦听器而不是简单地在编辑器中拖动它。 这是微不足道的:

whoa.AddListener(ScreenMaybeChanged);

(通常,您永远不必这样做。只需拖动即可连接。我只是为了完整性才提到这一点。)


这就是它的全部内容。

请注意 Internet 上有关此主题的过时示例代码。


上面显示了如何连接没有参数的简单函数。

如果您确实需要争论:

下面是一个函数有一个 FLOAT 参数的例子:

只需在文件顶部添加此代码:

[System.Serializable] public class _UnityEventFloat:UnityEvent<float> {}

然后照常进行。 就这么简单。

// ...
using UnityEngine.Events;

// add this magic line of code up top...
[System.Serializable] public class _UnityEventFloat:UnityEvent<float> {}

public class SomeThingHappens : MonoBehaviour
{
    // now proceed as usual:
    public _UnityEventFloat changedLength;
    
    void ProcessValues(float v)
    {
        // ...
        changedLength.Invoke(1.4455f);
    }
}

当您从其他函数拖动到此函数的编辑器插槽时:

一定要使用部分 - “动态浮动”。

在此处输入图片说明

(令人困惑的是,您的函数也将列在“静态参数”部分!这是 Unity 中的一个巨大陷阱!)

如果您只谈论几十个订阅者,请不要太担心订阅者的数量。 是的,一旦你进入数百或数千,优化它可能是一个好主意,但即便如此。 优化的第一条规则:不要优化。

所以:只需让每个实例订阅该事件并完成它。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM