我们的 Godot 游戏只在高配电脑上崩溃(原因如下)
Source: Dev.to
实际问题
我们追踪到四个相互叠加的独立问题。
1. 在游戏过程中加载资源
这看起来无害:
func start_boss_fight():
var boss_scene = load("res://scenes/InspectionBossFight.tscn")
var boss = boss_scene.instantiate()
load() 调用会在读取磁盘时冻结 100‑500 ms。再加上着色器编译,就会触发 Windows TDR(超时检测与恢复)。Windows 会在 GPU 驱动在约 2 秒内没有响应时终止进程。没有崩溃报告,只有卡死。
解决方案:在启动时预加载。
const InspectionBossFightScene = preload("res://scenes/InspectionBossFight.tscn")
func start_boss_fight():
var boss = InspectionBossFightScene.instantiate() # instant
对着色器材质也同样处理:在启动时创建模板,运行时复制,而不是实时创建。
2. 永久等待的 await
func _on_achievement_unlocked():
await EventBus.game_saved
show_notification()
如果保存失败且从未发出该信号,协程会永远等待,游戏卡死。
解决方案:发送后不等待。
func _on_achievement_unlocked():
EventBus.request_save.emit()
show_notification() # don't wait for confirmation
3. Tween 累积
每个 UI 动画都会创建一个新 tween,却从未销毁旧的。几小时后,成千上万的无用 tween 引用占据内存。
解决方案:跟踪并在创建新 tween 前销毁旧的。
var _active_tweens: Dictionary = {}
func fade_ambient_light():
if _active_tweens.has("ambient_fade") and _active_tweens["ambient_fade"].is_valid():
_active_tweens["ambient_fade"].kill()
var tween = create_tween()
_active_tweens["ambient_fade"] = tween
tween.tween_property(light, "energy", 0.5, 1.0)
4. 没有安全限制的循环
我们的 fighter‑cleanup 循环可能在单帧内遍历数千个无效条目:
func cleanup_fighters():
for i in range(fighters.size() - 1, -1, -1):
if not is_instance_valid(fighters[i]):
fighters.remove_at(i)
解决方案:添加迭代上限。
const MAX_ITERATIONS_PER_FRAME = 100
func cleanup_fighters():
var iterations = 0
for i in range(fighters.size() - 1, -1, -1):
iterations += 1
if iterations > MAX_ITERATIONS_PER_FRAME:
break
if not is_instance_valid(fighters[i]):
fighters.remove_at(i)
对于更大的操作(例如一次对 100+ 单位施加增益),将工作分块到多帧执行:
func apply_cascade_inspiration(units: Array):
var index = 0
while index = units.size():
break
units[index].apply_inspiration()
index += 1
await get_tree().process_frame
TL;DR
- 在启动时预加载资源。 在 Windows 上运行时的
load()可能导致 GPU 驱动超时。 - 不要
await可能永远不会触发的信号。 适当时使用“发送后不等待”模式。 - 跟踪你的 tweens。 在创建新 tween 前销毁旧的。
- 给循环加上上限。 尤其是处理动态数组的循环。
- 将大型操作分块到多帧。 这样可以保持主线程的响应性。
关键点:高端 PC 反而更快触发这些 bug,因为它们每秒执行的游戏循环更多。有时最好的硬件会暴露最糟糕的问题。
我们是 Lost Rabbit Digital,位于 GitHub。Starbrew Station 使用 Godot 4.5 构建。