02 · 事件与消息系统规范
所属文档集 ← 返回索引
摘要:定义游戏全局的事件通信规范、事件目录与发布/订阅契约。
目录
- 事件系统设计原则
- 事件类型体系
- 发布/订阅契约
- 全局事件目录
- 事件设计指导
1. 事件系统设计原则
| 原则 |
说明 |
| 最小载荷 |
事件只携带消费方需要的最少信息 |
| 类型安全 |
每个事件有明确的载荷类型,不使用无类型通用事件 |
| 无副作用传递 |
事件不携带可修改的对象引用,防止订阅方意外修改状态 |
| 单向通知 |
事件只通知"发生了什么",不携带"如何处理"的指令 |
| 有限生命周期 |
事件在发出后立即处理,不在系统间长期持有 |
2. 事件类型体系
2.1 按载荷分类
| 类型 |
描述 |
适用场景 |
Event<void> |
无载荷事件,纯通知 |
玩家死亡、游戏暂停 |
Event<T> |
单值载荷 |
HP 变化(传入新值) |
Event<Payload> |
结构体载荷 |
伤害事件(多字段) |
2.2 按作用范围分类
| 类型 |
作用范围 |
说明 |
| 全局事件 |
全游戏有效,跨场景 |
玩家死亡、游戏暂停、存档完成 |
| 局部事件 |
单场景/房间内有效 |
敌人死亡、机关触发、Boss 阶段变更 |
| 实体事件 |
单个实体范围 |
单个 NPC 对话开始、单个陷阱激活 |
3. 发布/订阅契约
3.1 发布方契约
发布方(Emitter)必须:
- 在系统初始化时注册事件频道
- 仅在状态确实发生变化时发出事件(不重复发出相同状态)
- 在系统销毁时清理事件频道
3.2 订阅方契约
订阅方(Listener)必须:
- 在系统初始化时注册订阅
- 在系统销毁时取消订阅(防止悬挂引用)
- 不在事件处理中再发出同类型事件(防止递归循环)
3.3 事件处理顺序
当多个系统订阅同一事件时,处理顺序不保证。
任何依赖特定顺序的逻辑应通过新增中间事件拆分为有序的因果链,而非依赖底层执行顺序。
4. 全局事件目录
4.1 玩家相关事件
| 事件名 |
载荷类型 |
发出方 |
典型订阅方 |
触发时机 |
OnPlayerDied |
void |
玩家系统 |
UI、音频、存档、世界 |
玩家 HP 归零 |
OnPlayerRevived |
void |
游戏管理器 |
玩家系统、UI、音频 |
复活流程完成 |
OnHPChanged |
{current: Integer, max: Integer} |
玩家系统 |
UI(HUD) |
HP 任意变化 |
OnSoulPowerChanged |
{current: Integer, max: Integer} |
玩家系统 |
UI(HUD) |
灵力变化 |
OnSpiritPowerChanged |
{current: Integer, max: Integer} |
玩家系统 |
UI(HUD) |
魄元变化 |
OnSpringChargesChanged |
{current: Integer, max: Integer} |
玩家系统 |
UI(HUD) |
灵泉次数变化 |
OnGeoChanged |
{current: Integer, delta: Integer} |
经济系统 |
UI(HUD) |
Geo 增减 |
OnAbilityUnlocked |
{abilityId: ID} |
进程系统 |
玩家系统、UI |
新能力获得 |
OnFormChanged |
{newFormId: ID} |
形态系统 |
UI、音频、武器系统 |
玩家切换形态 |
OnParrySuccess |
{counterWindowDuration: Duration} |
战斗系统 |
玩家系统、UI、音频 |
弹反判定成功 |
OnHitConfirmed |
HitPayload |
战斗系统 |
玩家系统(灵力积累)、反馈系统 |
攻击命中判定 |
4.2 敌人相关事件
| 事件名 |
载荷类型 |
发出方 |
典型订阅方 |
触发时机 |
OnEnemyDied |
{enemyId: ID, position: Vector2} |
敌人系统 |
进程系统、经济系统、叙事系统 |
敌人 HP 归零 |
OnEnemyHit |
HitPayload |
战斗系统 |
反馈系统、音频 |
攻击命中敌人 |
OnBossPhaseChanged |
{bossId: ID, phase: Integer} |
Boss 系统 |
UI、音频 |
Boss 进入新阶段 |
OnBossDefeated |
{bossId: ID} |
敌人系统 |
进程系统、叙事系统、存档 |
Boss 战胜利 |
4.3 世界/进程相关事件
| 事件名 |
载荷类型 |
发出方 |
典型订阅方 |
触发时机 |
OnSceneTransitionBegin |
{targetSceneId: ID} |
世界系统 |
UI(遮罩)、输入系统 |
开始场景切换 |
OnSceneTransitionEnd |
{sceneId: ID} |
世界系统 |
输入系统、音频 |
场景切换完成 |
OnSavePointActivated |
{savePointId: ID, position: Vector2} |
世界系统 |
存档系统、玩家系统、UI |
玩家激活存档点 |
OnRoomDiscovered |
{roomId: ID} |
世界系统 |
地图系统 |
玩家首次进入房间 |
OnCollectiblePickedUp |
{collectibleId: ID, type: CollectibleType} |
世界系统 |
进程系统、叙事系统 |
玩家拾取收集品 |
OnWorldFlagChanged |
{flagId: ID, value: Boolean} |
叙事系统 |
叙事系统(自引用)、进程系统 |
世界状态标志变化 |
4.4 UI/系统相关事件
| 事件名 |
载荷类型 |
发出方 |
典型订阅方 |
触发时机 |
OnGamePaused |
void |
游戏管理器 |
所有系统 |
暂停键触发 |
OnGameResumed |
void |
游戏管理器 |
所有系统 |
恢复键触发 |
OnSaveCompleted |
{slotId: Integer} |
存档系统 |
UI(提示) |
存档写入完成 |
OnSettingsChanged |
SettingsPayload |
设置系统 |
音频、无障碍、UI 等 |
设置项变更 |
OnAchievementUnlocked |
{achievementId: ID} |
成就系统 |
UI(Toast) |
成就达成 |
5. 事件设计指导
5.1 新增事件时的决策流程
5.2 载荷设计规范
好的载荷(值类型,信息完整):
不好的载荷(引用传递,导致耦合):
5.3 事件命名规范
| 规范 |
说明 |
示例 |
| 动词过去式(On + 名词 + 动词过去式) |
表示"已发生的事" |
OnPlayerDied、OnAbilityUnlocked |
| 变化类用 Changed |
状态数值变化 |
OnHPChanged、OnGeoChanged |
| 开始/结束对 |
持续性事件标注阶段 |
OnSceneTransitionBegin / OnSceneTransitionEnd |
| 避免"Will/Should" |
事件是通知,不是征询许可 |
❌ OnPlayerWillDie,✅ OnPlayerDied |