Unity中的简单事件系统

5 c# events unity-game-engine

我试图在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();
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

    }
}
Run Code Online (Sandbox Code Playgroud)

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

目标是所有应该在体育中心进行8到6班的工作人员,知道"完成日期"事件何时启动,但我不想订阅我实例化的每一个预制件.

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

Fat*_*tie 21

你必须使用UnityEvent.

    public UnityEvent whoa;
Run Code Online (Sandbox Code Playgroud)

这可不容易.制作一个脚本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;
    }
Run Code Online (Sandbox Code Playgroud)

把它放在游戏对象上.现在在Inspector中查看它.好吧?

只需将其他脚本拖到那里,就可以在"哇哇"发生时发生一些事情.

在此输入图像描述

就这么简单.要在BigScript中调用该事件,它就是

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

    private void YourFunction()
      {
      whoa.Invoke();
      }
Run Code Online (Sandbox Code Playgroud)

(如果你愿意的话if (whoa!=null) whoa.Invoke();)


在极少数情况下,您可能需要通过代码添加侦听器.

(我的意思是,而不是简单地在编辑器中拖动它.)

现在这很简单.请注意互联网上过时的示例代码.

whoa.AddListener(ScreenMaybeChanged);
Run Code Online (Sandbox Code Playgroud)

要明确:永远不要那样做 - 只需拖动即可连接.我只是提到完整性.


这里的所有都是它的.

请注意互联网上有关此主题的过时示例代码.*


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

如果你确实需要一个参数:

函数具有ONE FLOAT参数的示例:

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

[System.Serializable] public class _UnityEventFloat:UnityEvent<float> {}
Run Code Online (Sandbox Code Playgroud)

那你就定了.

...
using UnityEngine.Events;

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

public class SomeThingHappens : MonoBehaviour
{
    public _UnityEventFloat changedLength;
    public _UnityEventFloat changedHeight;

    ... and then ... 

    void ProcessValues(float v)
    {
        ....
        if (changedLength != null) changedLength.Invoke(1.4455f);
    }
}
Run Code Online (Sandbox Code Playgroud)

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

绝对确保使用的人上到顶层- "动态浮动".

在此输入图像描述

令人困惑的是,您的功能也将列在较低的"静态参数"部分中!

这是团结中的巨大骗局!

  • 嗨新手,传统的 c# 事件*在 Unity 上下文中不起作用*,因为它是一个 ECS 系统。*出于这个原因* Unity 创建了(出色的)UnityEvent 系统。关于您在多个系统上工作的事实 - 没什么大不了的。你必须是这两个方面的专家。这就是生活! (2认同)