在 Unity 开发中,不同模块之间的通信 是一个重要的挑战。传统的直接调用 或 观察者模式 有时会导致代码耦合过高,难以维护。
事件中心(Event Center) 是一种解耦的消息机制,允许不同组件之间低耦合地传递信息,从而提高代码的可维护性和扩展性。
本篇博客将详细介绍 事件中心的概念、使用场景、实现方式,以及在 Unity 中的应用。
1. 什么是事件中心?
事件中心(Event Center)是一种基于委托(Delegate)和事件(Event) 的消息管理系统,核心思想是发布-订阅模式(Publish-Subscribe)。
它包含两个主要部分:
- 发布者(Publisher) - 触发事件的对象(如玩家拾取道具、NPC 说话)
- 订阅者(Subscriber) - 监听并响应事件的对象(如 UI 显示道具、任务系统更新)
事件中心的工作流程
[事件中心]
├── 订阅者 1 监听 "敌人死亡" 事件
├── 订阅者 2 监听 "敌人死亡" 事件
├── 事件触发 → "敌人死亡" 事件广播
├── 订阅者 1 & 订阅者 2 同时执行回调
优点:
✅ 解耦:模块之间无需直接依赖,事件触发后自动通知所有监听者
✅ 易扩展:新功能只需注册监听事件,不影响原有代码
✅ 灵活性强:支持多种事件类型(UI、AI、游戏逻辑)
2. 事件中心的使用场景
事件中心适用于 多个系统需要监听同一事件 的情况,例如:
- UI 更新:玩家拾取道具,UI 更新显示
- 任务系统:玩家完成目标,任务系统检测完成状态
- 敌人 AI:某个敌人死亡,所有监听者都能收到消息
- 音效管理:某些动作触发时,播放相应的音效
3. 在 Unity 中实现事件中心
Unity 提供了 C# 委托(Delegate)和事件(Event),可以用来构建事件中心。
① 基于 C# 事件的简单事件中心
适用于 小型项目 或 简单的事件管理。
using System;
public static class EventCenter
{
public static event Action<int> OnEnemyDead; // 事件:敌人死亡(带参数)
public static void EnemyDead(int enemyID)
{
OnEnemyDead?.Invoke(enemyID); // 触发事件
}
}
// 订阅者 1:UI 更新
public class EnemyUI
{
public EnemyUI() { EventCenter.OnEnemyDead += UpdateUI; }
private void UpdateUI(int enemyID) => Console.WriteLine($"敌人 {enemyID} 死亡,更新 UI!");
}
// 订阅者 2:任务系统
public class QuestSystem
{
public QuestSystem() { EventCenter.OnEnemyDead += CheckQuest; }
private void CheckQuest(int enemyID) => Console.WriteLine($"敌人 {enemyID} 死亡,检查任务完成情况!");
}
// 测试
public class Game
{
public static void Main()
{
EnemyUI ui = new EnemyUI();
QuestSystem quest = new QuestSystem();
EventCenter.EnemyDead(101); // 触发事件,通知所有监听者
}
}
效果
敌人 101 死亡,更新 UI!
敌人 101 死亡,检查任务完成情况!
特点
✅ 代码简单,适合小项目
❌ 不支持动态事件管理(无法动态添加/移除事件类型)
② 基于 Dictionary 的通用事件中心
适用于 中大型项目,可以支持任意类型的事件。
using System;
using System.Collections.Generic;
public class EventCenter
{
private static Dictionary<string, Action<object>> eventDict = new Dictionary<string, Action<object>>();
public static void AddListener(string eventName, Action<object> listener)
{
if (!eventDict.ContainsKey(eventName))
eventDict[eventName] = null;
eventDict[eventName] += listener;
}
public static void RemoveListener(string eventName, Action<object> listener)
{
if (eventDict.ContainsKey(eventName))
eventDict[eventName] -= listener;
}
public static void TriggerEvent(string eventName, object param = null)
{
if (eventDict.ContainsKey(eventName))
eventDict[eventName]?.Invoke(param);
}
}
// 订阅者 1:UI 更新
public class EnemyUI
{
public EnemyUI() { EventCenter.AddListener("EnemyDead", UpdateUI); }
private void UpdateUI(object enemyID) => Console.WriteLine($"敌人 {enemyID} 死亡,更新 UI!");
}
// 订阅者 2:任务系统
public class QuestSystem
{
public QuestSystem() { EventCenter.AddListener("EnemyDead", CheckQuest); }
private void CheckQuest(object enemyID) => Console.WriteLine($"敌人 {enemyID} 死亡,检查任务完成情况!");
}
// 测试
public class Game
{
public static void Main()
{
EnemyUI ui = new EnemyUI();
QuestSystem quest = new QuestSystem();
EventCenter.TriggerEvent("EnemyDead", 101);
}
}
效果
敌人 101 死亡,更新 UI!
敌人 101 死亡,检查任务完成情况!
特点
✅ 支持动态注册和移除事件(适合大型项目)
✅ 事件名称自由,支持多个事件类型
✅ 低耦合,更适合模块化开发
4. 事件中心 vs 其他通信方式
通信方式 | 优势 | 劣势 | 适用场景 |
---|---|---|---|
直接调用 | 简单,直观 | 高耦合,扩展性差 | 单个类之间的调用 |
单例模式 | 方便访问全局对象 | 可能导致全局依赖 | 共享数据(如 UI 管理器) |
观察者模式 | 低耦合,支持多监听 | 代码较复杂 | 事件通知机制 |
事件中心 | 解耦、灵活、扩展性强 | 可能导致过多事件 | 大型项目、多人协作 |
5. 结论
事件中心的核心优势
✅ 模块解耦,各个系统之间无需直接依赖
✅ 提高扩展性,可以方便地增加新的监听者
✅ 支持多个事件类型,可灵活管理游戏逻辑
什么时候使用事件中心?
🔹 需要多个系统监听同一事件时(UI、任务系统、音效管理等)
🔹 需要解耦不同模块的依赖关系时
🔹 希望提高代码的扩展性和可维护性时
在 Unity 开发中,事件中心是一种非常强大的工具,掌握它可以让你的游戏架构更加清晰,开发效率更高!