FlyByWire A32NX 开发资源指南:调试工具、航电参考与 Community 目录本地开发工作流
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(目录联接),它不需要管理员权限,且只针对目录生效,是最适合本场景的选项(对比需要管理员权限的/Dsymbolic 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 提供了完整的自动化实现,其工作流程为:
- 自动探测 MSFS 的安装来源:先查 Steam 版路径
%APPDATA%\Microsoft Flight Simulator\UserCfg.opt,找不到再查微软商店版路径%USERPROFILE%\AppData\Local\Packages\Microsoft.FlightSimulator_8wekyb3d8bbwe\LocalCache\UserCfg.opt,两者都不存在则报错退出; - 从
UserCfg.opt中解析InstalledPackagesPath字段,从而定位真实的包安装目录(其中就包含 Community 文件夹); - 若 Community 下已存在旧的
flybywire-aircraft-a320-neo联接/文件夹,先删除再重建; - 执行
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 的日常开发流程可以归纳为:
- 初始化环境:克隆仓库后运行
./scripts/setup.sh(或 VSCodeSetup任务)安装依赖; - 构建:运行
Build A32NX任务生成out目录; - 链接:用 scripts/symlink_a32nx.cmd 或手动
mklink /J把out目录联接到游戏 Community 目录; - 调试:启动 MSFS 加载机模,借助 WebUI-DevKit 进行游戏内 console 查看与快速重载;必要时用 devtools-backend-refurb 获得更完整的 Chrome DevTools 能力;
- 迭代:修改
html_ui下的仪表源码或 behavior/src 下的 XML 行为定义,新增文件后重新构建(注意不提交out产物与自动生成的layout.json/manifest.json); - 提交:PR 中只包含源码改动,元数据交给 CI(如 .github/workflows/pr-build-fs2024.yml、master.yml)自动处理。
六、更多项目文档入口
如需进一步深入,仓库中还有以下与开发强相关的文档可供查阅:
- fbw-a32nx/docs:A32NX 项目专属文档目录,涵盖 a320-simvars.md(SimVar 清单)、a32nx-input-events.md(输入事件)、a320-coherent-triggers.md(Coherent 触发机制)等;
- docs/README.md:仓库总体结构与分支策略说明(
master面向 MSFS2024,fs2020-master面向 MSFS2020); - fbw-a32nx/README.md:A32NX 项目目录组织(
docs/src/out),其中out目录可随时删除并在下次构建时完全重建。
结语
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 等脚本,足以支撑一套完整、高效且贴近官方实践的本地开发工作流。