Godot 4 Checkpoint存档加载问题:重启无法从最近 checkpoint 续玩
Godot 2D游戏存档点系统问题修复
问题描述
我是游戏开发新手,正在用Godot开发首款2D游戏以熟悉平台功能。调试Checkpoint存档系统时遇到日志提示:'Checkpoint file does not exist',期望实现的核心功能是:关闭游戏重启后点击“开始”按钮,玩家能从最近到达的Checkpoint位置继续游戏。
核心问题分析
- 存档加载逻辑错误:
globals.gd的load_checkpoint_from_file函数中,错误地将current_checkpoint(原本应为节点引用)赋值为Vector2类型的位置数据,导致后续调用current_checkpoint.global_position时出现类型错误,同时重启游戏后节点已不存在,无法直接引用。 - 场景切换与玩家位置赋值顺序错误:
title_screen.gd中先设置Globals.player.position再切换场景,此时玩家节点尚未在目标场景中实例化,赋值操作无效。 - 退出保存机制不可靠:依赖
_exit_tree处理退出保存,在直接关闭窗口等场景下可能无法触发,导致存档丢失。 - 首次启动日志误解:首次启动时无存档文件,打印的
Checkpoint file does not exist是正常调试日志,并非报错,但需确保不影响游戏流程。
代码修复方案
1. 修改globals.gd(全局存档逻辑)
调整变量存储逻辑,区分运行时节点引用与持久化存档数据,同时优化退出保存机制:
extends Node var player = null var current_checkpoint = null # 运行时的存档点节点引用 var saved_checkpoint_scene: String = "" # 持久化的存档场景路径 var saved_checkpoint_position: Vector2 = Vector2.ZERO # 持久化的存档位置 var checkpoint_save_path = "user://checkpoint.sav" func _ready(): print("Globals script ready") load_checkpoint_from_file() # 用窗口退出通知替代_exit_tree,确保保存触发更可靠 func _notification(what): if what == NOTIFICATION_WM_QUIT_REQUEST: save_checkpoint() get_tree().quit() func respawn_player(): if player != null and saved_checkpoint_position != Vector2.ZERO: player.position = saved_checkpoint_position func load_checkpoint(): # 基于持久化数据返回存档信息,而非运行时节点 if saved_checkpoint_scene != "": return { "position": saved_checkpoint_position, "scene": saved_checkpoint_scene } return null func save_checkpoint(): if current_checkpoint != null: saved_checkpoint_scene = get_tree().current_scene.get_path() saved_checkpoint_position = current_checkpoint.global_position var file = FileAccess.open(checkpoint_save_path, FileAccess.WRITE) if file: file.store_pascal_string(saved_checkpoint_scene) file.store_var(saved_checkpoint_position) file.close() print("Checkpoint saved: ", saved_checkpoint_scene, saved_checkpoint_position) else: print("Error opening file for writing") func load_checkpoint_from_file(): if not FileAccess.file_exists(checkpoint_save_path): print("Checkpoint file does not exist (首次启动或无存档)") return var file = FileAccess.open(checkpoint_save_path, FileAccess.READ) if file: saved_checkpoint_scene = file.get_pascal_string() saved_checkpoint_position = file.get_var() as Vector2 file.close() print("Checkpoint loaded: ", saved_checkpoint_scene, saved_checkpoint_position) else: print("Error opening file for reading")
2. 修改title_screen.gd(标题场景逻辑)
调整场景切换与玩家位置赋值顺序,确保玩家节点实例化后再设置位置:
extends Control func _ready(): pass func _on_start_btn_pressed(): var checkpoint_data = Globals.load_checkpoint() if checkpoint_data != null: # 先切换到存档场景 var scene_change_result = get_tree().change_scene_to_file(checkpoint_data.scene) if scene_change_result == OK: # 等待场景加载完成,确保玩家节点已实例化 await get_tree().idle_frame if Globals.player != null: Globals.player.position = checkpoint_data.position else: get_tree().change_scene_to_file("res://levels/world_01.tscn") func _on_new_btn_pressed(): get_tree().change_scene_to_file("res://levels/world_01.tscn") func _on_credits_btn_pressed(): pass func _on_quit_btn_pressed(): Globals.save_checkpoint() get_tree().quit()
3. 其他代码无需修改
checkpoint.gd、world.gd、player.gd等文件的逻辑保持不变,因为运行时的存档点节点引用逻辑是正常的,仅需调整全局存档的持久化与加载逻辑。
验证步骤
- 运行游戏,到达任意存档点,触发存档(控制台会打印保存日志)。
- 关闭游戏后重启,点击“开始”按钮,玩家会直接出现在之前的存档点位置。
- 首次启动游戏时,控制台会打印
Checkpoint file does not exist (首次启动或无存档),但游戏会正常进入初始场景,无功能影响。
内容的提问来源于stack exchange,提问作者Neitan
相关产品推荐
相关产品推荐

