版本:Unity 6 (6000.0)
语言:英语
事件函数的执行顺序
跨帧拆分任务

Inspector 可配置自定义事件

Unity 提供了 UnityEvent API,作为 Unity 特定的替代方案,用于标准 C# 事件和委托。Unity 事件相对于标准 C# 事件的主要优势在于 Unity 事件是可序列化的,这意味着您可以在 Inspector 窗口 中对其进行配置。

可以将 UnityEvent 添加到任何 MonoBehaviour,并在运行时像标准 C# 委托一样执行。当在 MonoBehaviour 中声明 UnityEvent 时,它会显示在 Inspector一个 Unity 窗口,显示有关当前选定 GameObject、资产或项目设置的信息,允许您检查和编辑值。 更多信息
词汇表
窗口中,您可以在其中定义在编辑时间和运行时之间持续存在的回调。

Unity 事件与标准 C# 委托有类似的限制

  • 它们保存对目标对象的引用,这阻止目标对象被垃圾回收。
  • 如果您有托管 (C#) UnityEngine.Object 作为目标,并且非托管 (C++) 对应对象已被销毁,则不会调用回调。有关更多上下文,请参阅 空引用

配置 Unity 事件

先决条件

  • 创建一个包含 using UnityEngine.Events 的 MonoBehaviour 脚本
  • 声明至少一个 UnityEvent 类型的字段

在 Inspector 窗口中配置回调

  1. 选择包含已声明 UnityEvent 字段的脚本组件的 GameObjectUnity 场景中的基本对象,可以表示角色、道具、场景、相机、航路点等。GameObject 的功能由附加在其上的组件定义。 更多信息
    词汇表

  2. 单击事件名称下的 + 按钮以添加回调插槽。

  3. 选择要接收回调的 UnityEngine.Object。您可以使用对象选择器或将对象拖放到字段中。

  4. 选择事件发生时要调用的函数。下拉选择器将填充 GameObject 及其组件上的 适当方法 的筛选列表。

  5. 根据需要重复步骤 1-4 以添加同一事件的其他回调。

Configuring callbacks for events called Trigger Entered and Trigger Exited in the Inspector window
在 Inspector 窗口中为 Trigger Entered 和 Trigger Exited 事件配置回调

静态调用和动态调用

Inspector 窗口中配置 UnityEvent 时,支持两种类型的函数调用

  • 静态 调用在创作时完全预先配置,其目标和参数值在 Inspector 窗口中定义。当调用回调时,将使用在 Inspector 中定义的参数值调用目标函数。这适用于在运行时不会变化的值,例如当您想要在每次特定 碰撞当物理引擎检测到两个 GameObjects 的碰撞器接触或重叠时,就会发生碰撞,前提是至少有一个具有 Rigidbody 组件且处于运动状态。 更多信息
    词汇表
    发生时减少一定数量的健康值。静态绑定函数在函数选择列表中的 静态参数 下显示。
  • 动态 调用是从您的代码中以编程方式调用的,其参数与正在调用的 UnityEvent 的类型匹配。这适用于在运行时变化的值,例如表示角色在每次攻击时受到的伤害的 float 值。UI 会筛选回调,并且只显示签名对 UnityEvent 类型有效的动态函数。例如,如果您有一个 UnityEvent<string>,则函数选择器会在 动态字符串 标头下列出任何接受 string 参数的函数。
Choosing between static or dynamic functions whose signatures match the event type in the Inspector window
在 Inspector 窗口中选择签名与事件类型匹配的静态函数或动态函数

UnityEvent 中的泛型支持

默认情况下,Monobehaviour 中的 UnityEvent 会动态绑定到 void 函数。但您可以创建最多包含四个泛型类型参数的 UnityEvent,如以下示例所示

using UnityEngine;
using UnityEngine.Events;

public class GenericTest : MonoBehaviour
{
    public UnityEvent<int, int, bool, string> myEvent;
    
    // Start is called once before the first execution of Update after the MonoBehaviour is created
    void Start()
    {
        if (myEvent == null)
        {
            myEvent = new UnityEvent<int, int, bool, string>();
        }
        myEvent.AddListener(Ping);
    }

    // Update is called once per frame
    void Update()
    {
        if (Input.anyKeyDown && myEvent != null)
        {
            myEvent.Invoke(5, 6, true, "Hello");
        }
    }

    void Ping(int i, int j, bool print, string text)
    {
        if (print)
        {
            Debug.Log("Ping: " + text + i + j);
        }
    }
}

其他资源

事件函数的执行顺序
跨帧拆分任务