Skip to content

fix(app): reinitialize the engine when reopening RFVP games - #383

Merged
MadCcc merged 3 commits into
mainfrom
codex/fix-rfvp-reopen
Oct 25, 2026
Merged

MadCcc merged 3 commits into
mainfrom
codex/fix-rfvp-reopen

Conversation

@MadCcc

@MadCcc MadCcc commented Oct 24, 2026 •

Copy link
Copy Markdown
Contributor

RFVP 游戏首次启动正常,但退出回到媒体库后,在同一 App 进程内再次启动会弹出 engine is not initialized。本 PR 修复退出后的引擎重建,使游戏可以直接再次启动。

原因

退出流程调用 player.destroy_engine() 销毁内部引擎句柄,同时保留播放器 Node 和当前引擎类型。原来的 _switch_runtime_player() 只检查播放器对象和引擎类型,相同类型便直接返回成功。

RFVP 会在 _on_open_game() 之前设置 rfvp_encoding。第二次启动时,这个选项写入发生在句柄已销毁、初始化尚未执行的阶段,因此返回 INVALID_STATE,后续打开游戏的初始化路径也无法执行。首次启动正常,是因为 App 启动时已经初始化了句柄。

修复方案

  • 复用条件增加 player.is_initialized():播放器存在、引擎类型一致且句柄仍有效时才直接复用。
  • 退出后句柄已销毁时,走现有初始化流程,恢复渲染后端、引擎选项和画面效果,再设置 RFVP 编码并打开游戏。
  • 增加连续重开、选项恢复、初始化失败及失败后重试的回归检查。
  • 自动探针增加 launch_mode: "library",通过生产启动链路执行 RFVP 的前置选项;探针不会预先初始化引擎,从而能够检出原来的跳过初始化问题。
  • 自动探针记录句柄状态、播放器实例 ID、源帧及 Godot 实际呈现帧的统计值,并支持应用内退出当前游戏、游戏内自然退出后重开。iOS runner 跳过空种子目录的复制,由 App 初始化创建隔离测试目录。

iPad 真机自动测试

2026-10-25,在 iPad mini(A17 Pro)、iPadOS 26.5.2 上安装签名的 iOS arm64 Debug 测试包,启用 RFVP 和 AetherInternal,使用 《アストラエアの白き永遠》及显式 GBK 编码设置验证。游戏操作全部由脚本执行。

结果:23/23 步通过,0 个失败步骤;4 次启动、3 轮退出后重开,耗时 65.879 秒。

启动轮次 进入方式 结果
1 首次通过生产启动链路进入 成功,呈现游戏帧
2 应用内退出当前游戏回媒体库后再次启动 成功,重建引擎并呈现游戏帧
3 再次应用内退出当前游戏回媒体库后启动 成功,重建引擎并呈现游戏帧
4 游戏内 Exit → 确认 → 返回媒体库后启动 成功,重建引擎并呈现游戏帧

脚本还验证了:

  • 每次退出后引擎句柄已销毁、帧纹理已清空、媒体库已显示;重开时仍使用同一个播放器 Node,并恢复为已初始化状态。
  • 四轮源帧均为 1024×640,源帧可见采样占比 100%;实际 Godot 输出为 2266×1488,可见采样占比约 94.22%。
  • 四轮渲染错误均为 0;GPU bridge 的失败、复制失败、三角绘制失败和超时计数均为 0。
  • 本轮设备日志中 engine is not initialized、SCRIPT ERROR、Game launch failed 和 Tick failed 均为 0。
  • 最终 cleanup_complete.exit_code = 0,设备测试进程已停止;测试前的配置、游戏库和封面元数据已按字节恢复并校验。

验证范围为启动、退出后重开、输入触发游戏内退出、帧呈现和引擎清理。

其他验证

  • macOS 自动执行相同流程:23/23 步通过,4 次启动、3 轮退出重开。
  • macOS Debug 与 iOS arm64 Debug 原生构建、Godot 应用打包通过。
  • runtime_player_reopen_test.gd、runtime_regression_probe_test.gd、runtime_regression_touch_test.gd、RFVP 导入配置、启动入口、输入映射及存储切换检查通过。
  • Python runner 检查 5/5 通过;git diff --check 通过。

修复提交:06fbe06e。自动测试支持及 iPad 真机验证提交:cfb782d4。

合并前复查补齐了触屏回归测试中模拟播放器的 is_initialized() 接口(732602b3),并再次运行重开、探针、触屏三项 Godot 回归及 Python runner 的 5 项检查,全部通过。该提交仅修改测试夹具,生产逻辑和 iPad 自动测试使用的探针代码均未改动。

Returning to the library destroys the native engine while retaining the player Node and runtime kind. Reuse a matching player only while its engine remains initialized so RFVP can set its encoding before opening the next session.

Add behavioral regressions for repeated reopening, restored settings, initialization failure and retry. Validate the macOS Debug build with RFVP and AetherInternal enabled, five Godot script suites, and normal-library first launch, natural exit, second launch and Chinese story input in Astrea.
Add an opt-in library launch mode to the runtime regression probe so pre-open RFVP options execute through the production launch path without eager initialization. Record engine lifetime and actual presented-frame statistics, and cover host-requested and natural exits.

Skip empty iOS seed copies because the app creates the isolated writable root at initialization. Validation passed on macOS and an iPad mini (A17 Pro, iPadOS 26.5.2): 23 automatic steps, four RFVP sessions, two host exits, one natural game exit, presented frames, engine cleanup and process shutdown. Godot probe/reopen contracts and five Python runner checks also passed.
@MadCcc
MadCcc merged commit f1ef570 into main Oct 25, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant