yorickyao
yorickyao
发布于 2025-10-14 / 15 阅读
0
0

🧩基于Unity的简单框架工具类(3)

事件总线

1、概述

事件总线(EventBus)是一个基于观察者模式的通信机制,用于实现不同模块间的解耦通信。本实现采用静态门面类+内部实现类的双层架构设计,既保证了业务端使用的便捷性,又保持了内部实现的灵活性和可维护性。

2、架构设计

静态门面类(EventBus)

设计目的​:为业务代码提供简洁统一的API接口,隐藏内部实现细节。

核心特性​:

  • 完全静态方法,无需实例化即可使用

  • 方法签名简单明了,降低使用门槛

  • 作为业务层与实现层之间的桥梁

using System;

/// <summary>
/// 事件总线静态门面类,提供事件订阅、取消订阅和发布的统一接口。
/// </summary>
public static class EventBus
{
    // 订阅指定类型的事件。
    public static void Subscribe(string eventType, Action<object> callback)
        => EventBusImpl.Subscribe(eventType, callback);

    // 取消订阅指定类型的事件。
    public static void Unsubscribe(string eventType, Action<object> callback)
        => EventBusImpl.Unsubscribe(eventType, callback);

    // 发布指定类型的事件,并分发数据至所有订阅者。
    public static void Publish(string eventType, object data = null)
        => EventBusImpl.Publish(eventType, data);
}

内部实现类(EventBusImpl)

设计目的​:封装事件管理的核心逻辑,支持未来的功能扩展。

核心特性​:

  • 使用字典存储事件订阅关系

  • 实现事件的订阅、取消订阅和发布功能

  • 内部实现,对外部透明

using System;
using System.Collections.Generic;

/// <summary>
/// 消息总线实现类,负责事件的订阅、取消订阅及分发功能。
/// </summary>
internal static class EventBusImpl
{
    // 事件订阅者集合。
    private static readonly Dictionary<string, List<Action<object>>> _subscribers = new();

    // 订阅指定类型的事件。
    public static void Subscribe(string eventType, Action<object> callback)
    {
        if (!_subscribers.ContainsKey(eventType))
            _subscribers[eventType] = new List<Action<object>>();
        if (!_subscribers[eventType].Contains(callback))
            _subscribers[eventType].Add(callback);
    }

    // 取消订阅指定类型的事件。
    public static void Unsubscribe(string eventType, Action<object> callback)
    {
        if (_subscribers.ContainsKey(eventType))
            _subscribers[eventType].Remove(callback);
    }

    // 发布指定类型的事件,通知所有已订阅的回调方法。
    public static void Publish(string eventType, object data = null)
    {
        if (_subscribers.ContainsKey(eventType))
        {
            var callbacks = new List<Action<object>>(_subscribers[eventType]);
            foreach (var callback in callbacks)
            {
                callback?.Invoke(data);
            }
        }
    }
}

3、核心功能说明

事件订阅(Subscribe)

// 业务端使用示例
EventBus.Subscribe("PlayerDeath", OnPlayerDeathHandler);

private void OnPlayerDeathHandler(object data)
{
    // 处理玩家死亡事件
}

实现机制​:

  • 按事件类型分组存储回调方法

  • 自动去重,避免重复订阅

  • 线程安全的回调列表管理

事件发布(Publish)

// 业务端使用示例
EventBus.Publish("PlayerDeath", new { score = 100, reason = "enemy" });

实现机制​:

  • 遍历指定事件类型的所有订阅者

  • 使用副本列表进行回调,避免在迭代过程中修改原始集合

  • 支持空数据传递

事件取消订阅(Unsubscribe)

// 业务端使用示例
EventBus.Unsubscribe("PlayerDeath", OnPlayerDeathHandler);

实现机制​:

  • 精确匹配事件类型和回调方法

  • 安全的移除操作,避免空引用异常

4、特性说明

门面模式优势

  • 简化接口​:业务代码只需关注EventBus静态类

  • 降低耦合​:业务模块间通过事件通信,减少直接依赖

  • 易于维护​:内部实现变更不影响业务代码

性能优化

  • 使用Dictionary<string, List<Action<object>>>高效存储订阅关系

  • 发布时创建回调列表副本,确保迭代安全

  • 避免不必要的内存分配

类型安全

  • 使用强类型的事件类型标识

  • 统一的回调签名,便于调试和错误追踪

5、使用场景

游戏逻辑通信

  • UI与游戏逻辑的交互

  • 角色系统与战斗系统的通信

  • 场景切换事件通知

系统模块解耦

  • 成就系统与游戏进度的解耦

  • 音效系统与游戏事件的解耦

  • 存档系统与游戏状态的解耦

6、注意事项

  • 事件类型管理​:建议使用常量或枚举管理事件类型,避免字符串硬编码

  • 内存泄漏​:在对象销毁时务必取消相关事件订阅

  • 性能考虑​:避免在频繁触发的事件中执行复杂逻辑

  • 调试建议​:可为事件总线添加日志功能,便于调试事件流

事件总线类提供了轻量级、高性能的模块通信解决方案,是构建可维护游戏架构的重要基础工具。


评论