UnityEvent
简介定位为可视化而生方法注册所有类型(无参或者泛型)的UnityEvent都支持静态注册无参和单参方法参数类型授限。静态注册即在inspector面板上配置参数传递静态传递只支持单参数方法多参数必须在Invoke中动态传递。1.Inspector配置/纯代码绑定对于UnityEvent的使用根据是否需要Inspector可视化配置分为两种声明方式。1.1 Inspector配置在 Unity 中声明带参数的UnityEvent主要通过继承泛型类来实现。由于UnityEvent的泛型版本如UnityEventT是抽象类或需要在 Inspector 中序列化因此不能直接在字段中声明为new UnityEventint()并期望其在编辑器中完美工作。步骤一定义自定义事件类你需要创建一个继承自UnityEventT0, T1...的新类并加上[System.Serializable]特性以便在 Unity 编辑器的 Inspector 面板中显示和配置。必须添加[System.Serializable]特性否则该事件可能无法在 Inspector 中正确显示持久化监听器Persistent Listeners。注[System.Serializable]加在类或结构体定义上标记“这个类能被序列化”[SerializeField]管“字段”标记“这个私有字段要参与序列化并显示在 Inspector”。using UnityEngine; using UnityEngine.Events; //支持一个参数 [System.Serializable] public class IntEvent : UnityEventint { } //支持四个参数 [System.Serializable] public class MyCustomEvent : UnityEventstring, int, bool, float { }步骤二在 MonoBehaviour 中使用在你的脚本中声明上述自定义类的公共字段。public class EventExample : MonoBehaviour { // 在 Inspector 中可以看到这个字段并可以添加监听者 //此处声明后并未初始化应该是Unity在inspector生成中进行了初始化 public IntEvent onScoreChanged; void Start() { // 代码动态添加监听 onScoreChanged.AddListener(HandleScoreChange); } void Update() { if (Input.GetKeyDown(KeyCode.Space)) { // 触发事件传入参数 onScoreChanged.Invoke(100); } } // 监听方法签名必须与泛型参数匹配 void HandleScoreChange(int score) { Debug.Log(Current Score: score); } }将脚本添加至游戏对象则在inspector面板中可看到如下设置界面1.2 纯代码方式不需要Inspector配置如果你不需要在 Unity 编辑器的 Inspector 面板中绑定事件即所有监听器都通过代码动态添加那么你可以不创建子类直接使用泛型实例。using UnityEngine; using UnityEngine.Events; public class CodeOnlyEvent : MonoBehaviour { // 直接声明泛型字段无需创建子类 private UnityEventint myEvent new UnityEventint(); void Start() { // 必须通过代码添加监听 myEvent.AddListener(HandleNumber); // 触发 myEvent.Invoke(42); } void HandleNumber(int num) { Debug.Log(num); } }缺点在 Inspector 中不可见。无法保存持久化监听器Persistent Listeners。通常用于纯代码架构或临时事件。1.3 测试疑问针对inspector配置须通过继承泛型类来实现这个说法在以下测试代码中发现直接声明UnityEvent字段在inspector中也是可编辑和配置的呀有点懵了。此外并不需要去做初始化关于这个的解释如下对于public或[SerializeField]标记的这些受支持类型Unity 会在序列化阶段自动实例化它们所以即使你不写 new UnityEventint()它也不会为 null且在 Inspector 中可见。using UnityEngine.UIElements; using UnityEngine; using UnityEngine.Events; public class EventExample : MonoBehaviour { // 在 Inspector 中可以看到这个字段并可以添加监听者 public IntEvent onScoreChanged; public UnityEvent onTest; public UnityEventint onTest2; public UnityEventPlayerData onTest3; public UnityEventint,float onTest4; private void Awake() { } void Start() { if (onTest ! null) { Debug.Log(OnTest initialize); } if (onTest2 ! null) { Debug.Log(OnTest2 initialize); } if (onTest3 ! null) { Debug.Log(OnTest3 initialize); } if (onTest4 ! null) { Debug.Log(OnTest4 initialize); } // 代码动态添加监听 onScoreChanged.AddListener(HandleScoreChange); } void Update() { if (Input.GetKeyDown(KeyCode.Space)) { // 触发事件传入参数 onScoreChanged.Invoke(100); } } // 监听方法签名必须与泛型参数匹配 void HandleScoreChange(int score) { Debug.Log(Current Score: score); } } [System.Serializable] public class IntEvent : UnityEventint { } [System.Serializable] public struct PlayerData { public int id; public string name; }2. 使用 C# 原生Action/Delegate替代方案如果你觉得 UnityEvent 的声明太繁琐且不需要 Inspector 可视化可以使用 C# 原生的Action或event。这在代码层面更简洁但功能不同。using System; using UnityEngine; public class ActionExample : MonoBehaviour { // 声明简单支持任意数量参数 public event Actionint, string OnDataReceived; void Trigger() { // 触发前检查 null OnDataReceived?.Invoke(100, Hello); } }