Skip to content
Development
Skill

/godot-save-system

Godot 4 存档系统设计,包含资源序列化、加密存储、存档管理和数据回滚。

BOOST
From plugin
alphaagent
10419 skills
Install
$ npx -y skills add 925236118/AlphaAgent --skill godot-save-system --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/godot-save-system

Context preview

The summary Claude sees to decide when to auto-load this skill.

Godot 4 存档系统设计,包含资源序列化、加密存储、存档管理和数据回滚。

SKILL.md

godot-save-system.SKILL.md
name: godot-save-system
description: Godot 4 存档系统设计,包含资源序列化、加密存储、存档管理和数据回滚。

Godot 存档系统设计

概述

存档系统是游戏的核心功能之一,负责保存和加载玩家数据。Godot 提供了 FileAccess、ResourceSaver 等工具,结合 JSON 或二进制格式实现存档功能。

1. 存档管理器

1.1 核心实现

# save_manager.gd (Autoload)
extends Node

const SAVE_PATH := "user://savegame.save"
const ENCRYPTION_KEY := "your_secret_key_here"

signal save_completed
signal load_completed
signal save_error(message: String)

func save_game(data: Dictionary) -> void:
    var file := FileAccess.open_encrypted_with_pass(
        SAVE_PATH,
        FileAccess.WRITE,
        ENCRYPTION_KEY
    )

    if file == null:
        save_error.emit("Could not open save file")
        return

    var json := JSON.stringify(data)
    file.store_string(json)
    file.close()

    save_completed.emit()

func load_game() -> Dictionary:
    if not FileAccess.file_exists(SAVE_PATH):
        return {}

    var file := FileAccess.open_encrypted_with_pass(
        SAVE_PATH,
        FileAccess.READ,
        ENCRYPTION_KEY
    )

    if file == null:
        save_error.emit("Could not open save file")
        return {}

    var json := file.get_as_text()
    file.close()

    var parsed := JSON.parse_string(json)
    if parsed == null:
        save_error.emit("Could not parse save data")
        return {}

    load_completed.emit()
    return parsed

func delete_save() -> void:
    if FileAccess.file_exists(SAVE_PATH):
        DirAccess.remove_absolute(SAVE_PATH)

func has_save() -> bool:
    return FileAccess.file_exists(SAVE_PATH)

2. 可存档对象

2.1 Saveable 基类

# saveable.gd
class_name Saveable
extends Node

@export var save_id: String

func _ready() -> void:
    if save_id.is_empty():
        save_id = str(get_path())

func get_save_data() -> Dictionary:
    var parent := get_parent()
    var data := {"id": save_id}

    if parent is Node2D:
        data["position"] = {"x": parent.position.x, "y": parent.position.y}

    if parent.has_method("get_custom_save_data"):
        data.merge(parent.get_custom_save_data())

    return data

func load_save_data(data: Dictionary) -> void:
    var parent := get_parent()

    if data.has("position") and parent is Node2D:
        parent.position = Vector2(data.position.x, data.position.y)

    if parent.has_method("load_custom_save_data"):
        parent.load_custom_save_data(data)

2.2 使用示例

# 玩家自定义存档数据
class_name Player
extends CharacterBody2D

func get_custom_save_data() -> Dictionary:
    return {
        "health": health_component.current_health,
        "inventory": inventory_component.list(),
        "level": level
    }

func load_custom_save_data(data: Dictionary) -> void:
    health_component.current_health = data.health
    level = data.level

3. 存档数据结构

3.1 完整存档格式

{
    "version": "1.0.0",
    "timestamp": 1712236800,
    "player": {
        "id": "player",
        "position": {"x": 100.0, "y": 200.0},
        "health": 80,
        "level": 5,
        "inventory": [...]
    },
    "world": {
        "enemies_killed": 42,
        "time_elapsed": 3600.0
    },
    "settings": {
        "difficulty": "normal",
        "sound_volume": 0.8
    }
}

4. 场景状态管理

# scene_save_manager.gd
class_name SceneSaveManager
extends Node

@export var saveable_groups: Array[String] = ["saveable"]

func capture_scene_state() -> Dictionary:
    var save_data := {}

    for group in saveable_groups:
        for node in get_tree().get_nodes_in_group(group):
            if node is Saveable:
                save_data[node.save_id] = node.get_save_data()

    return save_data

func restore_scene_state(data: Dictionary) -> void:
    for save_id in data.keys():
        var node = get_node_or_null(save_id)
        if node and node is Saveable:
            node.load_save_data(data[save_id])

5. 自动保存机制

# auto_save.gd
class_name AutoSave
extends Node

@export var auto_save_interval: float = 300.0  # 5分钟
@export var save_on_exit: bool = true

var _timer: float = 0.0

func _ready() -> void:
    if save_on_exit:
        get_tree().node_removed.connect(_on_node_removed)

func _process(delta: float) -> void:
    _timer += delta
    if _timer >= auto_save_interval:
        _timer = 0.0
        perform_save()

func perform_save() -> void:
    var scene_state := SceneSaveManager.capture_scene_state()
    var full_data := {
        "version": ProjectSettings.get_setting("application/config/version"),
        "timestamp": Time.get_unix_time_from_system(),
        "scene": saveable_groups,
        "data": scene_state
    }
    SaveManager.save_game(full_data)

func _on_node_removed(node: Node) -> void:
    if node is Player:
        perform_save()

6. 设计模式总结

| 模式 | 应用场景 | |------|----------| | **备忘录模式** | 保存/恢复对象状态 | | **观察者模式** | 信号通知存档状态变化 | | **外观模式** | SaveManager 提供统一存档接口 | | **策略模式** | 支持多种存档格式(JSON、二进制) |

7. 注意事项

| 注意事项 | 说明 | |----------|------| | **数据验证** | 加载前验证存档版本和完整性 | | **向后兼容** | 处理旧版本存档的字段缺失 | | **加密存储** | 敏感数据使用加密 | | **异步操作** | 大型存档使用异步读写 |

Read more
Ships withalphaagent

为Godot引擎编辑器开发的Ai Agent插件

Get the whole plugin

Other skills on alphaagent.

godot-tscn-format
Skill

godot-tscn-format

Godot 4.x .tscn 场景文件纯文本格式规范与 AI 操作指南 — 文件结构、资源引用、 Transform 变换、属性值格式、信号连接,以及 AI 直接读写 .tscn 文件的操作方法。