406 字
2 分钟
游戏设计模式03——极简事件中心
TIP本方法适用于小型项目。核心思路是一个事件对应一个
static event字段,再配一个触发方法,不用字典,也不用字符串当 key。
核心代码
using System;using UnityEngine;
public static class EventCenter{ // 无参事件 public static event Action OnSelect; public static void RaiseSelect() => OnSelect?.Invoke();
// 带参事件 public static event Action<int> OnScoreChanged; public static void RaiseScoreChanged(int score) => OnScoreChanged?.Invoke(score);
// 进入 Play 模式时清空,防止关闭 Domain Reload 后残留旧订阅 [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)] private static void ResetAll() { OnSelect = null; OnScoreChanged = null; }}外部订阅/触发方式
订阅方
public class SelectUI : MonoBehaviour{ private void OnEnable() => EventCenter.OnSelect += HandleSelect; private void OnDisable() => EventCenter.OnSelect -= HandleSelect;
private void HandleSelect() { Debug.Log("选中了"); }}触发方
EventCenter.RaiseSelect();EventCenter.RaiseScoreChanged(100);优点
- 简单直观:一个事件就是一个字段加一个方法。
- 类型安全:拼错字名字会直接编译报错。
- 好追踪:在 IDE 里对事件”查找所有引用”,就能看到所有订阅方和触发方。
- 几乎零开销: 没有字典查找,没有类型转换,也没有 GC。
- event 关键字能保护订阅: 外部只能 += 和 -=,不能直接调用事件,也不能写 = null 清掉别人的订阅。所以需要用 RaiseXxx() 来触发。
注意事项
- 成对取消订阅(最重要): 订阅写在 OnEnable,取消写在 OnDisable。静态事件会一直持有订阅对象的引用,不取消就会内存泄漏,或者报 MissingReferenceException。
- 不要用 Lambda 订阅: OnSelect += () => {…} 之后没法取消,应该用方法名。
- Domain Reload: 关闭 Domain Reload 后,静态事件会保留上次运行的订阅,所以要在 ResetAll() 里清空。