FlyByWire A32NX 开发资源指南:调试工具、航电参考与 Community 目录本地开发工作流

原创2026-10-12 10:57:041,944 阅读
文章标签:游戏开发

FlyByWire A32NX 开发资源指南:调试工具、航电参考与 Community 目录本地开发工作流

本文围绕 FlyByWire A32NX(开源 A320neo 微软模拟飞行机模项目)的 Development Resources 文档 展开,系统梳理了 html-ui 内容的游戏内调试工具、航电仪表开发所需的 XML Gauge 参考,以及两条对开发效率影响最大的工作流建议——不要手动提交 layout.json/manifest.json、通过 symlink(目录联接)直接在游戏的 Community 目录中迭代开发。读完本文,你将掌握 A32NX 开发环境的搭建要点、热重载式调试方法,并理解其构建管线为何会自动重写这两个打包元数据文件。

一、开发工具:针对 html-ui 内容的调试利器

A32NX 的座舱仪表(PFD、ND、MCDU、ISIS 等)大量由 HTML/JS 驱动,这些内容位于 fbw-a32nx/src/base/flybywire-aircraft-a320-neo/html_ui 目录下(如 html_ui/Pages/VCockpit/Instruments/A32NX/MCDU、ND、PFD)。微软模拟飞行(MSFS2020/2024)的 Coherent GT 渲染引擎负责运行这些页面,而常规浏览器开发者工具在这里并不直接可用,因此社区开发了两个专用工具来弥补调试能力的缺口。

WebUI-DevKit:游戏内的开发调试浮层

由社区开发者维护的 WebUI-DevKit 是一个游戏内(in-game)开发 overlay,专门服务于 html-ui 内容,提供三项核心能力:

  • 快速重载(fast reload):修改 html-ui 源码后无需重启模拟器即可刷新界面,显著缩短"改代码 → 看效果"的迭代周期;
  • 控制台输出(console output):在游戏内直接查看 JavaScript 的 console 日志,解决 Coherent GT 环境下"看不到报错"的痛点;
  • 除此之外还集成了元素检查、网络面板等常见调试能力,方便定位样式与逻辑问题。

它面向的正是上文提到的 html_ui 目录下的仪表代码。对于希望实时观察自己改动效果、又不想反复重启 MSFS 的开发者,这是首选的辅助工具。

devtools-backend-refurb:面向 Coherent GT 的 Chrome DevTools

devtools-backend-refurb 则是一个 Chrome devtools server,目标是把标准浏览器开发工具(Chrome DevTools)协议适配到 Coherent GT 渲染引擎上,从而让开发者用熟悉的 DevTools 界面调试 html-ui 内容。

需要特别注意两点(文档亦明确提示):

  • 该项目仍处于 work in progress(WIP)阶段;
  • 它倾向于表现得很不稳定(tends to be very finnicky)。

因此建议把它当作进阶工具使用:在 WebUI-DevKit 无法满足需求、需要断点调试或深入分析网络请求时再尝试;日常开发中若遇到连接失败、断点不命中等问题,应首先回归 WebUI-DevKit 或直接查看游戏内 console 输出。

二、航电/显示开发参考:P3D XML Gauge Reference

A32NX 的座舱交互行为大量通过 XML Gauge 与行为定义(behavior)实现,仓库中可见大量相关定义,例如 fbw-a32nx/src/behavior/src/A32NX_Interior_*.xml 系列,以及 ModelBehaviorDefs 下的模型行为定义。

资源文档指出,P3D(Prepar3D)官方的 XML Gauge Reference(来自 Prepar3D SDK 的 "Panels and Gauges SDK / creating XML gauges" 章节)仍然是撰写和阅读此类 XML Gauge 的有效参考资料,并且依然适用于 MSFS2020。原因在于 MSFS 的仪表/行为系统在 XML Gauge 层面与 P3D 保持了较大的兼容性,P3D 时代积累的 gauge 编写经验(<Element>、<Update>、<Select>、绑定 SimVar 等模式)在 FS2020 上依旧成立。

实操建议:

  • 开发新仪表逻辑时,可先查阅该 P3D SDK 参考理解 XML Gauge 的基础语法;
  • 再结合本仓库已有的行为定义文件(fbw-a32nx/src/behavior/src)对照学习项目内部的写法惯例;
  • 涉及 SimVar 时,可交叉查阅项目维护的 a320-simvars.md 与 a32nx-input-events.md 文档,确保使用正确的变量名与事件名。

三、工作流 Tip 1:不要把 layout.json 和 manifest.json 的改动提交进 PR

为什么 CI 会自动处理这两个文件

layout.json 与 manifest.json 是 MSFS 机模包(package)的元数据文件:

  • layout.json 记录了包内全部文件的路径、大小与时间戳(content 条目),MSFS 依据它进行文件装载与增量更新;
  • manifest.json 声明包的标题、版本、依赖、total_package_size 等安装信息。

在 A32NX 仓库中,这两个文件并非手写维护,而是构建时由脚本自动生成。最直接的源码证据是 scripts/build_a32nx.js:

  • 其内部 readdir() 遍历构建产物目录时,显式跳过 layout.json 与 manifest.json(见该文件 readdir 生成器中的 continue 逻辑),确保不会把旧元数据当作源文件;
  • createPackageFiles() 会遍历 fbw-a32nx/out/flybywire-aircraft-a320-neo 下的所有文件,重新计算每个条目的 size 与 date,并覆写生成新的 layout.json;
  • manifest.json 则基于源码中的模板 fbw-a32nx/src/base/manifest-base.json(内含 creator、title、dependencies、content_type、minimum_game_version、manufacturer 等固定字段)合并生成,并追加 title 后缀(如 (Development)、(PR #xxxx))、package_version(版本号加 commit hash)以及 total_package_size 等构建期信息。

对应地,package.json 中的 build-a32nx:manifest 脚本就是 node scripts/build_a32nx.js,它被纳入完整构建流程。

手动提交会带来什么问题

正因为这两个文件在每次构建时都会被重新生成,任何 PR 中手动修改它们的内容:

  • 必然与 CI 重新生成的结果冲突——由于文件内容由构建环境决定(文件列表、大小、时间戳、版本后缀),他人构建或 CI 构建后会出现大量无意义 diff;
  • 经常导致多余的 merge conflict,拖慢 PR 合并;
  • 文件列表还可能因缺失/多余条目引发安装异常。

文档给出的结论很明确:PR 中不要包含对这两个文件的手动修改,交给 CI 自动更新即可。

为什么不要在 fork 上激活 GitHub Actions

同理,如果你 fork 了仓库并在自己的 fork 上开启了 GitHub Actions(workflow),每次 push 都会触发 fork 上的 CI 构建,而构建会改写这些元数据文件(甚至以新的提交形式推回你的分支),从而进一步放大上述冲突问题。因此文档建议:避免在 fork 上激活 GitHub Actions,让 CI 只在主仓库的 PR 流程中运行。这与仓库工作流的配置也相互印证——例如 .github/workflows/master.yml 中的构建 job 还显式限制了只在主仓库(github.repository_owner == 'flybywiresim')运行。

四、工作流 Tip 2:用 symlink 把本地仓库链接到 Community 目录

这是本地开发效率提升最关键的一步。默认情况下,要测试机模改动需要把构建产物复制到游戏的 Community 文件夹;而通过 symlink(Windows 术语叫 directory junction,目录联接)可以把"游戏读取的位置"直接指向"你的本地构建目录",从而免去反复复制文件的流程。

原理与收益

  • 在你的本地仓库与游戏的 Community 文件夹之间建立联接后,游戏读取的机模就是 fbw-a32nx/out/flybywire-aircraft-a320-neo 这个构建输出目录(构建目录的生成机制可参考 fbw-a32nx/README.md 中 out 目录说明);
  • 对于可热重载(hot-reloadable)的文件(如 html-ui 的 JS/HTML 仪表代码),修改后能在游戏中实时反映,无需重新打包、无需复制文件,同时仍然保留一个规范的开发环境;
  • 配合第一节的 WebUI-DevKit 快速重载能力,即可形成"改代码 → 游戏内即时生效"的流畅开发闭环。

操作步骤(官方文档流程)

第 1 步:先移除游戏中已安装的旧版本机模。

确保 Community 目录下不存在旧的 flybywire-aircraft-a320-neo 文件夹(或其残留联接),避免新旧版本同时加载造成冲突。

第 2 步:在 cmd(命令提示符)中执行以下命令建立联接。

请把命令中的两个路径替换为你机器的实际路径:

mklink /J "C:\users\<user>\AppData\Microsoft Flight Simulator\Packages\Community\flybywire-aircraft-a320-neo" "C:\path\to\cloned\repo\flybywire-aircraft-a320-neo"

参数说明:

  • /J 表示创建 directory junction(目录联接),它不需要管理员权限,且只针对目录生效,是最适合本场景的选项(对比需要管理员权限的 /D symbolic link);
  • 第一个参数是联接的存放位置,即游戏 Community 目录下将要出现的机模文件夹路径。注意 MSFS 的 Community 目录具体位置取决于你的安装来源(Steam 版通常在 %APPDATA%\Microsoft Flight Simulator\Packages\Community,微软商店版则在 %USERPROFILE%\AppData\Local\Packages\Microsoft.FlightSimulator_8wekyb3d8bbwe\LocalCache\Packages\Community 附近,具体以 UserCfg.opt 中的 InstalledPackagesPath 为准);
  • 第二个参数是联接的目标,即你本地仓库中机模构建输出的真实目录:<仓库根目录>\fbw-a32nx\out\flybywire-aircraft-a320-neo(该目录由构建脚本创建)。

第 3 步:每次新增文件后重新构建,但不要提交构建结果。

文档强调:每当添加了新文件,需要运行构建命令(npm run build 或 VSCode 中的 build task),让新的文件进入 out 输出目录并被 build_a32nx.js 重新写入 layout.json 的文件清单;但不要提交构建产物(包括重新生成的 layout.json/manifest.json 与 out 目录本身)。

仓库自带的自动化方案:scripts/symlink_a32nx.cmd

如果你的仓库版本包含该脚本,甚至不必手敲 mklink 命令。仓库中的 scripts/symlink_a32nx.cmd 提供了完整的自动化实现,其工作流程为:

  1. 自动探测 MSFS 的安装来源:先查 Steam 版路径 %APPDATA%\Microsoft Flight Simulator\UserCfg.opt,找不到再查微软商店版路径 %USERPROFILE%\AppData\Local\Packages\Microsoft.FlightSimulator_8wekyb3d8bbwe\LocalCache\UserCfg.opt,两者都不存在则报错退出;
  2. 从 UserCfg.opt 中解析 InstalledPackagesPath 字段,从而定位真实的包安装目录(其中就包含 Community 文件夹);
  3. 若 Community 下已存在旧的 flybywire-aircraft-a320-neo 联接/文件夹,先删除再重建;
  4. 执行 MKLINK /J 将 %communityFolder%\Community\flybywire-aircraft-a320-neo 联接到本仓库的 fbw-a32nx\out\flybywire-aircraft-a320-neo。

这个脚本与文档中的手动命令本质相同,但替你完成了路径探测与旧安装清理,可作为参考模板理解整个联接流程。

构建命令与 VSCode 任务

完整构建 A32NX 的推荐入口有两个:

  • VSCode build task:仓库的 .vscode/tasks.json 定义了 Build A32NX 任务,其命令为 ./scripts/build.sh -r a32nx(在 Windows 上通过 scripts/dev-env/run.cmd 调用),可以直接从 VSCode 的终端任务菜单触发;
  • 命令行:在仓库根目录运行 ./scripts/build.sh -r a32nx(需要先执行 ./scripts/setup.sh 完成依赖与开发环境初始化,VSCode 的 Setup 任务同样封装了该步骤)。

构建过程会顺带执行 package.json 中定义的 build-a32nx:copy-base-files、build-a32nx:instruments、build-a32nx:manifest(即 node scripts/build_a32nx.js)等一系列子任务,最终产出可被 MSFS 加载的 fbw-a32nx/out/flybywire-aircraft-a320-neo 包目录。值得注意的是,文档语境中的 npm run build 属于概括性说法,当前仓库的完整构建链路以 scripts/build.sh 与 VSCode tasks 为准。

五、开发环境全景:把各环节串起来

将以上资源组合起来,A32NX 的日常开发流程可以归纳为:

  1. 初始化环境:克隆仓库后运行 ./scripts/setup.sh(或 VSCode Setup 任务)安装依赖;
  2. 构建:运行 Build A32NX 任务生成 out 目录;
  3. 链接:用 scripts/symlink_a32nx.cmd 或手动 mklink /J 把 out 目录联接到游戏 Community 目录;
  4. 调试:启动 MSFS 加载机模,借助 WebUI-DevKit 进行游戏内 console 查看与快速重载;必要时用 devtools-backend-refurb 获得更完整的 Chrome DevTools 能力;
  5. 迭代:修改 html_ui 下的仪表源码或 behavior/src 下的 XML 行为定义,新增文件后重新构建(注意不提交 out 产物与自动生成的 layout.json/manifest.json);
  6. 提交:PR 中只包含源码改动,元数据交给 CI(如 .github/workflows/pr-build-fs2024.yml、master.yml)自动处理。

六、更多项目文档入口

如需进一步深入,仓库中还有以下与开发强相关的文档可供查阅:

结语

A32NX 的日常开发并非只围绕飞行逻辑本身,调试 html-ui 仪表、维护 XML Gauge 行为定义、以及处理好与游戏安装目录和 CI 构建的关系,同样是开发者需要掌握的基本功。本文介绍的四个要点——WebUI-DevKit 与 devtools-backend-refurb 的分工、P3D XML Gauge 参考的沿用价值、layout.json/manifest.json 的自动生成机制、以及 Community 目录联接开发法——正是 FlyByWire 团队沉淀下来的核心开发经验,配合仓库中的 build_a32nx.js 与 symlink_a32nx.cmd 等脚本,足以支撑一套完整、高效且贴近官方实践的本地开发工作流。

登录后查看全文
aircraft