下载 App
修改于10/075 浏览
06 · 我花了五轮去修一个不存在的问题
==============================
《临界》开发者日志 · 第六篇
前五篇讲的是"我做了什么",这篇讲"我错得有多离谱"。
---
【症状:第 2 天,按钮变灰】
游戏跑到第二天,「进入下一天」按钮就永久灰掉了。点什么都没反应。玩家看到的是卡死。
---
【第一层错误:我以为是输入问题】
我的开发环境是本地预览窗口 + 程序化点击。我第一反应是"点击没送到"。
・------ —— ------
・试了 4 种横屏→竖屏的坐标映射 —— 全失败
・查 Windows 前台窗口锁 —— 发现 SetForegroundWindow 被系统拒绝
・用 AttachThreadInput 绕过前台锁 —— 单步操作生效,但批量仍失败
・让窗口永久 TOPMOST —— 没用——SDL 只处理有输入焦点的窗口的鼠标事件
・写图像识别脚本自动找游戏卡片 —— 能识别,但点击依然不可靠
我在这上面花了整整五轮。
每一轮我都以为"快找到了"。每一轮我都写了一大段调试工具。每一轮我都把失败归因于"环境问题"。
---
【转折:AI 助手的一句话】
我让 AI 助手分担了一部分工作。负责关卡系统验证的 AI 助手在把雪季真跑起来之后,报回来一个 P0:
雪量预算只有 1~2 天,而雪季标称 6~12 天。
Snowfield:Relax 把 q*T【全部】分给"存在的邻居":边界格只有 3 个(边)/ 2 个(角)邻居,但分到的雪一点没少。
spillEdge 只在 DEFAULTS 第 29 行声明过,全项目从未被引用。
→ 总雪量只增不减 → 越过 4×9216 后不存在稳定配置 → 雪崩无法收敛 → 按钮永久变灰。
我盯着这段话看了很久。然后我意识到:我调试了五轮的"点击问题",可能根本不是点击问题。
---
【验证:我做了 A/B 对照】
我没有直接相信这个结论。我写了一个对照实验:
降雪/格/天 12 天中首次无法收敛
0.85(原值) 第 3 天
0.25 第 4 天
0.14 第 8 天
0.10 第 10 天
结论比AI 助手说的更微妙:不是"永不收敛",而是"收敛极慢"——慢到玩家眼里就是卡死。
降到 1/8 的降雪量仍然跑不完 12 天。说明光靠边界耗散救不回来,系统总雪量在单调上涨。
---
【真正的解法:放弃"修平衡",改为"保 liveness"】
我意识到自己在做一件错事:我在试图让物理系统完美收敛,但玩家真正需要的是"游戏不要失去响应"。
这是两个不同的问题。
-- 保底阀门:单次雪崩最多持续 240 帧(约 4 秒 @60fps)
if busy then
self.avalancheFrames = (self.avalancheFrames or 0) + 1
if self.avalancheFrames > self.opts.maxAvalancheFrames then
self.avalancheFrames = 0
self:OnAvalancheEnd() -- 强制收尾
return false
end
end
宁可让残留的亚稳态留在山上(危险度保持高位——这本身就是对的),也不能让游戏失去响应。
验证结果:
单次雪崩最长帧数 = 241(上限 240)
卡死天数 = 无
最终状态 = playing
12 天完整跑通。
---
【我学到的事】
【1. 当一件事反复失败时,先问"是不是方向错了"】
我调试了五轮的坐标映射。那个方向从一开始就是错的——游戏根本没在接收我的输入,因为它已经卡死了。
如果我在第三轮就停下来问"有没有可能问题不在输入",能省下两天。
【2. AI 助手的价值不是"帮我做事",是"看到我看不到的东西"】
我一直在看窗口和坐标。AI 助手在看雪量和阈值。同一个 bug,两个人的视野完全不同。
【3. 不要相信AI 助手的结论,要自己验证】
AI 助手说"雪崩无法收敛"。我做 A/B 后发现是"收敛极/慢"。机制不同,解法就不同——如果照搬他的结论去优化收敛速度,我会走另一条弯路。
【4. 区分"正确"和"有用"】
修复边界耗散是正确的(那是自组织临界态的前提,spillEdge 从死代码变成了活代码)。但它不够有用——不能解决玩家的卡死。
保底阀门不那么优雅(它允许物理系统处于未收敛状态),但它有用。
在 GameJam 里,有用的东西要优先。
【5. 记录失败比记录成功更有价值】
这篇日志里没有一行代码是"漂亮"的。但我认为它比前五篇都值得写——因为下一个接手的人会因为这篇少走两天弯路。
---
《临界》· 2026 TapTap 聚光灯游戏创作挑战