template/docs/intermediate/replay-commands.md
unanmed 687e248ac1 docs(10-11): 用户修订循环 batch3(基础/其他 + 高级教程预留)
- U-01 src-tour:content 层主要在编辑器内改、对应初级教程
- U-02 data-state-overview:解释 state 静态类型按 L0-L3 逐层累加
- U-04 map-structure:按 alias/zIndex 取指定图层(非 addLayer)
- U-05 map-tiles:putMapData/getMapData 完整示例 + 高级教程预留
- U-06 flags:区分字段对象与字段值,两组接口如何选择
- U-20 events:以内置事件集已完整(发布前约 100 个)视角改写
- U-21 replay-commands:录像指令细节留高级教程
- U-22 11 篇:高级教程显式说明 + 非链接预留标记
2026-10-18 14:45:00 +08:00

4.3 KiB
Raw Blame History

录像指令

录像验证要能重放出和原来一模一样的结果,前提是:把该记下来的操作都记下来。录像系统(state.replaySystem)做的正是这件事——把玩家在游戏中的操作记录成一条条录像步,之后可以重新播放。它的主要用途是录像验证:只运行数据端、重放录像,就能确认同样的操作是否得到同样的结果(原理见数据端与渲染端)。

核心原则

:::info 核心原则 玩家直接产生、会影响最终成绩的行为,必须计入录像。 :::

这句话包含两个条件:

  • 玩家直接产生:是玩家亲手做出的操作,例如移动、使用道具、装备道具。由代码或时间自动发生的变化不算;
  • 会影响最终成绩:这个操作会改变游戏结果。只改渲染表现、不进数据端的操作不算。

满足两个条件的操作,都必须作为一条录像步记录下来。否则重放这条录像时,玩家的操作没有被重新执行,结果就会与原始游玩对不上。

主动录像与被动录像

录像步分两类,由 ReplayCommandType 表示:

  • 主动录像(Active):指令自己就会执行对应的操作。引擎内置的移动、瞬移、使用道具(见勇士道具)、装备(见勇士装备)都是主动录像;
  • 被动录像(Passive):指令不自己执行,而是让外部通过录像沙盒的 getPassive() 取到这一步的参数,再由外部决定怎么处理。

新增自定义录像指令

录像指令属于引擎内容,需要改动 packages-user 下的包(这个目录是什么、和 src 是什么关系,见 src 导览 的「包从哪来」),而不是只在 src 里写几行代码。新增一条自定义录像指令大致分三步:

  1. 在录像指令码枚举 ReplayCode 中分配一个新码。该枚举属于录像格式的一部分,遵循「只增不改」——新语义必须用新码,不能复用旧码;
  2. 实现 IReplayCommand:type 指明是主动还是被动录像,execute(step) 执行这一步对应的操作并返回 ReplayCommandResult;若需要「连续步骤的后处理」,再实现可选的 finalize();
  3. 用 state.replaySystem.registerCommand(code, command) 把指令注册进录像系统。引擎内置指令的注册代码在 src/data/replay/initialize.ts 中。

execute 的返回值 ReplayCommandResult 有三种:Success(成功)、Failed(失败)、Ignored(失败但可忽略,继续执行后续录像,并会在控制台输出信息)。

录像安全检测:@shouldReplay 与 @ignoreReplay

@shouldReplay(message) 与 @ignoreReplay(message) 写在一个方法的上方,形如 @名字(...)。这种以 @ 开头的写法叫装饰器(decorator):它不改变方法本身的代码,只给这个方法附加一条额外说明(在这里,就是给录像系统打一个标记)。装饰器的基础写法见代码基础。

录像系统会检查「一步录像执行后,游戏是否真的记录下了新的录像步」。为了让这个检查覆盖到正确的方法,可以用两个方法装饰器给方法打标:

  • @shouldReplay(message):把方法标记为应该计入录像。它会为这次检查登记一段区间,并把 message 作为信息记录;一旦检查发现问题,就用这些信息告诉你哪些调用路径没有被计入录像;
  • @ignoreReplay(message):把方法标记为忽略本次录像检查,一般用于异步内容等不会立刻修改状态的方法。

检测区间的开始与结束由录像系统在每步录像执行前后统一控制:执行前开始收集,执行后结束并核对区间内是否产生了新的录像步。若没有,就在控制台输出告警,并列出登记过却未被计入的 @shouldReplay 路径。

:::warning 不要用 @ignoreReplay 来掩盖控制台的录像告警。它只应用于「确实不该计入录像」的方法,滥用很可能导致录像出错。 :::

录像指令的更多细节(内置指令各自怎么实现、录像格式与沙盒机制等)会在高级教程中讲解(预留标记:高级教程 · 录像指令);待高级教程就位后,此处会替换为链接。