【Unity】事件分发系统的使用示例
1. 定义事件处理器
首先,创建一个脚本 ChessGenerator.cs
,用于处理棋子生成逻辑:
using UnityEngine;public class ChessGenerator : MonoBehaviour, IGameplayObserver
{private void Start(){// 订阅事件(通过接口)EventDispatcher.instance.Regist(EventDef.EVENT_GENERATE_CHESS, this);// 订阅事件(通过委托)EventDispatcher.instance.Regist(EventDef.EVENT_GENERATE_CHESS, OnChessGeneratedDelegate);}// 通过接口实现的事件处理public void OnEventTriggered(string eventName, params object[] args){if (eventName == EventDef.EVENT_GENERATE_CHESS){Debug.Log($"通过接口收到事件: 生成棋子,参数: {args[0]}");}}// 通过委托实现的事件处理private void OnChessGeneratedDelegate(params object[] args){Debug.Log($"通过委托收到事件: 生成棋子,参数: {args[0]}");}private void OnDestroy(){// 注销事件(可选,防止内存泄漏)EventDispatcher.instance.UnRegist(EventDef.EVENT_GENERATE_CHESS, OnChessGeneratedDelegate);}
}
2. 发布事件
在另一个脚本(如 GameManager.cs
)中发布事件:
using UnityEngine;public class GameManager : MonoBehaviour
{private void Update(){if (Input.GetKeyDown(KeyCode.Space)){// 发布事件,附带参数(例如棋子类型)EventDispatcher.instance.DispatchEvent(EventDef.EVENT_GENERATE_CHESS, false, // 是否使用对象池(此处为false)"国王" // 事件参数);}}
}
3. 使用对象池优化
如果需要高频触发事件(如每秒生成多个棋子),可以使用对象池优化:
// 修改 ChessGenerator.cs 的订阅逻辑
EventDispatcher.instance.RegistWithPool(EventDef.EVENT_GENERATE_CHESS, OnChessGeneratedDelegate);// 修改 GameManager.cs 的发布逻辑
EventDispatcher.instance.DispatchEvent(EventDef.EVENT_GENERATE_CHESS, true, // 启用对象池"士兵"
);
4. 运行效果
- 按下空格键时,
GameManager
发布EVENT_GENERATE_CHESS
事件。 ChessGenerator
会同时触发两种处理逻辑:- 接口方式:输出
通过接口收到事件: 生成棋子,参数: 国王
。 - 委托方式:输出
通过委托收到事件: 生成棋子,参数: 国王
。
- 接口方式:输出
- 如果启用对象池,处理器会从
EventHandlerPool
中复用,减少内存分配。
5. 关键点说明
- 事件名称:使用
EventDef.EVENT_GENERATE_CHESS
避免硬编码。 - 多订阅支持:同一个事件可以同时通过接口和委托订阅。
- 对象池:高频事件建议使用
RegistWithPool
和DispatchEvent(..., true)
。 - 资源释放:在
OnDestroy
中注销事件,防止场景切换后残留订阅。
6. 扩展场景
- 参数传递:可以通过
object[]
传递多个参数,如棋子类型、位置、颜色等:EventDispatcher.instance.DispatchEvent(EventDef.EVENT_GENERATE_CHESS, false,"皇后", new Vector3(1, 0, 0), Color.white );
- 动态订阅:根据游戏状态动态注册/注销事件(如暂停时停止处理)。
通过这个示例,可以清晰看到事件系统的解耦优势: GameManager
无需知道谁处理事件, ChessGenerator
也无需知道事件如何触发。