引言
在项目进行到一半时升级游戏引擎,是游戏开发中最令人胆战心惊的日常决策之一。新的 Godot 版本也许修复了正卡住你的那个 bug — 但也可能悄无声息地弄坏你投入了半年心血的场景。正因如此,Godot 社区里经验丰富的开发者把版本升级当作一次风险决策,而不是例行公事。
本指南并不是在鼓吹"永远升级"。它是一份针对 Godot 4.x 到 4.x 迁移的风险管理检查清单:如何判断到底要不要升级、如何做好准备以便能安全退回、哪些地方在版本之间已知会出问题,以及 — 最重要的 — 如何切实验证没有任何东西损坏。
到底该不该升级?
在动手之前,先诚实地回答这个问题。升级有实实在在的成本(迁移工作 + 重新测试),所以收益也必须同样实在。
应该升级的情况
- 上游已修复的 bug 正在卡住你。 如果困扰你的问题在更新的版本里已经修复,那么升级通常比永远背着一个变通方案更划算。
- 某个新功能对你的游戏有实质性好处。 不是"听起来不错" — 而是能实实在在节省开发时间,或者解锁你需要的某种设计。
- 你的开发周期很长。 如果项目要做好几年,小步频繁地跳(每次一个次要版本)远比最后来一次巨大的跳跃安全。差距只会越拉越大。
不该升级的情况
- 临近发布。 发售前的几周是引入引擎级变更的最糟糕时机。先发布,之后再升级。
- 你需要 C# + Web 导出。 C# 项目的 Web 导出在 Godot 4.x 中仍然不可用(在 godot#70796 中跟踪)。如果你在 3.x 依赖这项功能,迁到 4.x 就会失去它。
- 你的目标是老旧硬件。 Godot 3.x 能在 OpenGL 2 级别的 GPU 上运行;而 Godot 4 的 Compatibility 渲染器需要 OpenGL 3.3 / WebGL 2。如果你的玩家群体用的是老机器,3.x 可能确实才是正确的引擎。
- 关键插件尚未更新。 如果项目依赖的某个插件不支持新版本,你就会在自己的迁移问题之上再背上它的迁移问题。
经验法则:当一个具体的收益超过你估算出的具体成本时才升级 — 而不是因为新版本发布了。
升级之前 — 准备检查清单
这里的每一步都是为了:万一升级出了问题,你损失的是一个下午,而不是一个项目。
- 提交所有更改并创建升级分支。 绝不要直接升级项目的唯一副本。有了专用分支(不用 git 的话就完整复制一份文件夹),回滚只是一条命令,而不是一场抢救行动。
- 记录当前的精确版本(例如具体是哪个 4.x.y 构建,标准版还是 .NET 版)。当你需要回退或提交 bug 报告时会用得上。
- 保留旧的编辑器可执行文件。 Godot 各版本可以并行安装 — 编辑器只是一个可执行文件,两个都留着没有任何成本,还能让你随时用旧编辑器打开旧分支。
-
列出你的插件并逐一检查其支持的版本。 翻一遍
addons/,记下每个插件的来源,并在其仓库或 Asset Library 页面上确认它支持目标版本。 - 阅读你跨越的每一个版本的官方升级说明。 官方迁移指南是按版本编写的 — 如果你从 4.2 升到 4.4,就要把 4.3 和 4.4 的说明都读一遍。
- 留下"已知正常"的证据。 给关键场景截图、录一段简短的游玩视频,或者 — 最好的办法 — 编写自动化测试场景(下面的测试章节会详细展开)。升级之后,"看起来和表现是否一样?"这个问题,只有在你事先记录了"一样"的标准时才有答案。
升级流程
- 用新编辑器打开分支副本。 打开的是升级分支,不是 main。新编辑器会提示进行转换/重新导入 — 接受即可。
-
让它完成重新导入。
.godot文件夹会从零重新生成。大项目的首次导入可能要花一段时间,而第一轮导入期间打印的警告通常无害。 - 检查 Output 面板和 Debugger 中新出现的错误。 与升级前就存在的错误做对比(你事先记下来了吧?)。新增的错误就是这次迁移的待办清单。
- 把关键路径实际玩一遍。 开始新游戏、加载存档、跑一遍核心玩法循环、打开主要菜单。编辑器阶段的错误是容易的那部分 — 回归问题藏在运行时行为里。
- 运行你的测试场景(升级前准备好的那些),并与基线结果对比。
-
提交前用 git 检查工作区的差异。 迁移过程中编辑器会重写文件:
project.godot会加入新的配置值,.tscn文件会被重新保存,还可能出现新的.uid文件。审查一遍 diff,弄清楚到底改了什么 — 然后把它作为一个标注清晰的迁移提交一次性提交。
4.x 版本之间的已知破坏点
Godot 4 的次要版本之间大体上兼容,但"大体上"这个词在这句话里可不轻松。以下是根据官方说明和社区报告整理的最容易踩坑的变更。
4.2 → 4.3:TileMap 被弃用,改用 TileMapLayer
Godot 4.3 弃用了 TileMap 节点,改用 TileMapLayer — 每个图层一个节点,而不是把图层放在一个节点里。现有的 TileMap 仍能工作,但新代码和新项目应该使用 TileMapLayer。编辑器自带一个提取工具:选中你的 TileMap,打开底部的 TileMap 面板,点击右上角的工具箱图标,选择 "Extract TileMap layers as individual TileMapLayer nodes"。
社区报告的坑:有报告称 TileMapLayer 迁移后,TileSet 物理层的碰撞位被重置为默认值。它并非人人都会遇到,但故障形态很恶劣(物体不再碰撞,且没有任何报错)。转换之后请显式地验证你的瓦片碰撞。
4.3 → 4.4:.uid 文件与 GDScript 新增功能
-
Godot 4.4 新增了
.uid伴随文件,出现在脚本和着色器旁边。请把它们提交到版本控制 — 删除它们可能会破坏所有用到uid://引用的地方(官方 4.4 升级说明覆盖了相关变更,例如@export_file路径改为uid://)。它们看起来像垃圾文件;但并不是。 - 类型化 Dictionary 等 GDScript 新增功能是向后兼容的 — 你的旧代码可以照常运行。但采用了新功能的插件在旧版本上会停止工作,因此跨版本时插件的行为可能有所不同。
一般情况:任何次要版本之间的微妙变化
次要版本之间的渲染调整可能会微妙地改变游戏的观感 — 光照、抗锯齿、2D 吸附。社区讨论中还有一些在全新项目中无法复现的场景特有回归:某个场景升级后行为异常,但在干净的项目里重建同一个场景却一切正常。如果出现莫名其妙的问题,试试这套隔离流程:关闭编辑器,删除 .godot 文件夹,重新打开并让所有内容重新导入;如果问题依旧,就在干净的项目中复现该场景,以判断罪魁祸首是项目积累的状态,还是引擎本身的变更。
3.x → 4.x 完全是另一回事
上面的一切都是关于 4.x 到 4.x 的跨越。从 Godot 3 迁移到 Godot 4 完全是另一个量级:GDScript 语法变了,大量节点被重命名,TileMap、物理和渲染都被从头重做 — 而且大多数插件需要专门的 4.x 版本。对于大型 3.x 项目,迁移成本可能接近重写的成本,值不值得做是一个真正因项目而异的决定。那次迁移值得(也确实有)自己专门的文档;本文不会假装能覆盖它。
升级后的测试 — 真正的瓶颈
说点实在的:开发者回避升级的头号原因并不是迁移本身 — 而是手工验证"没有任何东西损坏"的代价太高。中等规模的游戏跑一遍完整的手动回归测试,一个周末就没了。而玩家在发售后发现的运行时 bug,比任何编辑器错误都糟糕得多,因为它已经不是待办事项,而是口碑问题。
最低限度的手动冒烟测试
- 从标题画面开始一局新游戏
- 加载一份已有的存档
- 把核心玩法循环玩上几分钟
- 在你支持的每种分辨率和窗口模式下检查 UI
把前后对比自动化
手动测试无法规模化,也没法告诉你某个精灵偏移了两个像素。Godot QA 正是为此而生 — 一个免费、MIT 许可、开源的 Godot 测试运行器。它的工作流与版本升级完美契合:
- 升级之前,编写(或录制)覆盖关键路径的场景 JSON 文件,并在旧版本上截取基线截图。
- 升级之后,在新版本上运行完全相同的场景,并与基线做像素级对比。
- 失败之处直接指出回归的位置,几分钟就能搞定原本要花整个周末的手动重玩。
一个场景不过是一份由步骤组成的 JSON 列表 — 输入、等待、断言、截图:
{
"name": "core_loop_smoke",
"steps": [
{"type": "wait", "seconds": 1.0},
{"type": "input", "action": "ui_accept", "pressed": true},
{"type": "wait", "seconds": 0.5},
{"type": "assert", "node_path": "/root/Main/Player",
"property": "health", "expected": 100, "operator": "eq"},
{"type": "input", "action": "move_right", "pressed": true},
{"type": "wait", "seconds": 2.0},
{"type": "input", "action": "move_right", "pressed": false},
{"type": "assert", "node_path": "/root/Main/Player",
"property": "position:x", "expected": 100.0, "operator": "gt"},
{"type": "screenshot", "name": "after_move"}
]
}
这套场景格式与 Godot MCP Pro 的 run_test_scenario 工具所用的完全相同,因此连接到编辑器的 AI 助手可以替你编写这些场景。
如果出了问题
- 按版本做二分排查。 如果你一次跨了多个次要版本,就一个次要版本一个次要版本地重试升级,找出到底是在哪里坏的。这样排查范围就从"所有东西"缩小到一份 changelog。
-
清空
.godot文件夹,让项目重新导入。升级后各种诡异问题里,有相当一部分出人意料地源于陈旧的导入缓存。 - 用你的精确错误信息去搜索引擎的 GitHub issues。 如果是真正的回归,往往已经有人报告过 — 有时还附带变通方案。
- 检查是不是某个插件在作怪。 在项目设置中禁用你的插件后重新测试。如果问题消失了,那就是插件的问题 — 在怪罪引擎之前,先看看有没有更新的版本发布。
- 接受"留在旧版本"也是一种正当的结果。 如果修复成本超过了升级的收益,就回退分支、按兵不动,并设个提醒等下一个版本发布时再试。这不是失败 — 这是风险管理在发挥作用。
什么时候按兵不动才是正确选择
有些项目就是不应该升级,这一点值得直说:已发售或即将发售的游戏、需要 Web 导出的 C# 项目、面向老旧硬件的游戏,以及基于深度修改的自定义引擎构建的项目。在所有这些情况下,你正在用的版本都在尽职尽责。升级是工具,不是美德 — 目标是一款完成的游戏,而不是一个崭新的引擎。
常见问题
升级之后还能降级吗?
不能,至少没有可靠的方法。一旦新编辑器重新保存了你的场景和资源,它们就不再向后兼容旧编辑器。安全回退的唯一途径是从版本控制中恢复 — 这正是升级分支存在的意义。
可以一次跳过好几个版本吗?
小步跳更安全。官方升级说明是按版本编写的,所以每一跳都有明确的检查清单 — 一次跨多个版本会把所有清单同时叠加在一起,让你更难分辨是哪个变更弄坏了什么。
次要版本真的会弄坏东西吗?
很少,但确实会。大多数项目跨次要版本都没有问题,但社区报告的边缘案例是存在的 — 碰撞位被重置、场景特有的渲染回归。这正是升级前基线测试重要的原因:它们把"是不是坏了什么?"从一种感觉变成一次测量。
这份清单适用于 3.x → 4.x 吗?
清单本身适用 — 建分支、保留旧的可执行文件、留下基线、事后测试。破坏点列表则不适用:3 到 4 的迁移规模大得多(GDScript 语法、节点重命名、系统重做),并且有自己专门的官方文档。