Godot Engine平台游戏:如何实现Hub World关卡物品的条件存档
Godot 平台跳跃游戏关卡收集物存档实现方案
核心设计原则
严格分离临时会话状态与永久存档状态,从机制上保证只有通关、抵达checkpoint的收集进度才会落盘,中途退出的收集行为完全不生效。
数据结构设计
在全局Autoload单例中拆分两套收集状态存储,避免直接把运行时状态写进永久存档:
temp_level_collectibles:内存中的临时字典,结构为{ 关卡唯一ID: [已拾取物品ID列表] }。仅记录当前关卡本次游玩过程中拾取的物品,游戏切场景、退出时如果没有触发保存条件,会直接被丢弃,不写入存档文件。persistent_collectibles:嵌套字典结构,存储真正需要持久化的收集状态,结构为{ 关卡唯一ID: { 物品ID: 是否已收集 } }。只有这个结构的数据会最终写入本地存档文件。- 所有可收集物品不要在自身节点上存储收集状态,每次关卡场景加载时,统一从
persistent_collectibles读取对应物品ID的状态,决定是否生成、是否可交互,避免节点销毁/重载时状态丢失。
拾取流程逻辑
玩家拾取物品时,仅更新临时状态,不触碰永久存档:
- 物品碰到玩家碰撞体时,播放拾取特效、临时更新本次游玩的资源计数,随后销毁节点
- 通过全局信号把拾取的物品ID、所属关卡ID发送到Autoload单例
- 单例接收到信号后,仅把对应物品ID追加到当前关卡的
temp_level_collectibles列表中
参考实现代码:
# 可收集物品节点的核心脚本 signal collected(item_id: String, level_id: String) @export var item_id: String @export var level_id: String func _on_body_entered(body: Node2D): if body.is_in_group("Player"): collected.emit(item_id, level_id) queue_free()
# Autoload单例的信号接收逻辑 var temp_level_collectibles = {} func _on_collectible_picked(item_id: String, level_id: String): if not temp_level_collectibles.has(level_id): temp_level_collectibles[level_id] = [] if item_id not in temp_level_collectibles[level_id]: temp_level_collectibles[level_id].append(item_id)
永久保存的触发判定
仅当满足以下两个场景时,才会把临时收集数据合并到永久存档结构,其他所有操作(中途回Hub、关游戏、崩溃退出)都不触发合并:
- 玩家抵达关卡终点、触发通关判定
- 玩家触发任意checkpoint的激活判定
通用提交保存的函数实现:
func commit_collectible_progress(level_id: String): # 把临时收集列表合并到永久存档结构 if not persistent_collectibles.has(level_id): persistent_collectibles[level_id] = {} for item_id in temp_level_collectibles.get(level_id, []): persistent_collectibles[level_id][item_id] = true # 合并完成后清空对应关卡的临时数据,避免重复写入 temp_level_collectibles.erase(level_id) # 此时再执行本地存档写入操作 write_save_file()
两个触发点的接入方式:
- 关卡终点检测区域:触发通关判定时,调用
commit_collectible_progress(当前关卡ID),随后再切换回Hub World场景 - Checkpoint检测区域:激活checkpoint、设置玩家重生点时,同步调用
commit_collectible_progress(当前关卡ID)。后续从该checkpoint继续游玩时,新拾取的物品依然会进入临时列表,等下一个checkpoint触发或通关时再执行提交。
边界场景适配
因为临时状态和永久状态完全隔离,所有未触发提交的收集行为都不会写入存档:
- 玩家中途退出关卡返回Hub、直接关闭游戏窗口时,对应关卡的临时收集列表会随内存回收直接丢弃,下次重新进入该关卡时,所有收集物会按照永久存档里的状态刷新,之前中途拾取的物品会重新出现,完全符合需求。
- 注意不要在物品被拾取的瞬间就调用存档写入函数,否则会导致未触发checkpoint/通关的拾取行为被永久保存,违背设计规则。
内容的提问来源于stack exchange,提问作者zak_250
相关产品推荐
相关产品推荐

