Token导航 LogoToken导航

Agent Skill · 开发

godot-save-load-systems(godot 保存加载系统)

godot-save-load-systems 用于处理 GitHub 仓库、Issue、Pull Request 和代码协作信息,适合在 Codex、Claude、Cursor、Gemini CLI 中需要围绕仓库状态、代码变更或协作事项进行整理时使用。可结合来源仓库、安装命令和原始 README 继续核验具体用法。安装前建议确认权限范围、维护状态,以及是否会触发联网、命令执行或文件读写。

godot-save-load-systems 是开发类 Agent Skill,可用宿主为 Codex、Claude、Cursor、Gemini CLI,通过GitHub 仓库获取,权限为可写文件;许可证信息还不明确,第三方扫描有未通过项,按安装量在开发类的 21,746 个 Skill 里排第 7,944。

总安装 3,442周安装 142GitHub Stars 138下载 1,125核验 2026-05-01

安装说明

本站只整理中文说明,不托管安装包,也不代用户安装。
GitHub
许可证
unknown

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:godot-save-load-systems(godot 保存加载系统)
来源仓库:https://github.com/thedivergentai/gd-agentic-skills
仓库路径:skills/godot-save-load-systems
安装命令:
npx skills add https://github.com/thedivergentai/gd-agentic-skills --skill godot-save-load-systems
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。该命令会通过 npx skills 从第三方来源获取 Skill;本站只展示命令,不托管安装包,也不自动执行。

skills.shnpx skills
npx skills add https://github.com/thedivergentai/gd-agentic-skills --skill godot-save-load-systems

这个 Skill 是做什么的

开发类 Skill 面向写代码、改代码和排查问题,一般会读写仓库文件,部分还会执行构建或测试命令。

用于处理 GitHub 仓库、Issue、Pull Request 和代码协作信息,支持项目状态跟踪。适用于围绕仓库变更、代码审查或团队协作事项进行信息整理。通过 npx skills add 命令从指定 GitHub 仓库安装并使用。安装前需确认权限范围、维护状态及是否触发联网或文件操作。

godot-save-load-systems 属于开发类 Skill,可作为该场景下的辅助能力补充。

来源仓库内路径:skills/godot-save-load-systems

上手步骤

4 步
  1. 1

    确认自己的宿主工具

    公开资料标注支持 Codex、Claude、Cursor、Gemini CLI;先确认自己用的是其中之一,再按对应工具的 Skills 目录放置。

  2. 2

    拿到安装命令

    可以直接复制的命令是 npx skills add https://github.com/thedivergentai/gd-agentic-skills --skill godot…;命令里的占位符换成自己的路径或密钥再执行。

  3. 3

    安装后重启宿主

    命令执行完要完全退出宿主工具再打开,让新装的 Skill 被重新扫描到,否则列表里可能看不到。

  4. 4

    按最小权限试用

    它需要可写文件,先在测试目录或测试账号里跑,确认没问题再放到正式项目。

常见问题

6 条

godot-save-load-systems 怎么安装?

在终端执行 npx skills add https://github.com/thedivergentai/gd-agentic-skills --skill godot-save-load…。装完完全退出宿主工具再打开,让它重新扫描本地 Skill。

godot-save-load-systems 支持哪些 AI 工具?

公开资料标注支持 Codex、Claude、Cursor、Gemini CLI。其他工具只要能读取本地 Skill 目录,一般也能手动放进去,但要自己确认触发方式是否一致。

godot-save-load-systems 需要什么权限?

权限级别是可写文件。该 Skill 可能写入或修改本地文件,使用前需要确认目标目录和修改范围。

godot-save-load-systems 是免费的吗?

公开资料没有标注明确许可证,收费和商用限制都无法确认。正式使用前请到来源仓库核对授权说明。

godot-save-load-systems 用的人多吗?

公开数据是累计安装 3,442 次,近一周安装 142 次,下载 1,125 次,GitHub 138 星。这些数字来自第三方目录统计,只能当作热度参考,不代表质量或安全性。

godot-save-load-systems 安全吗?

第三方扫描有未通过项,风险较高。除非你确认过源码,否则不建议直接安装到常用环境。

值得选的地方和要先想清楚的地方

值得选的地方

  • 同时适配 4 种工具,换客户端不用重新找替代品。

先想清楚的地方

  • 许可证没有明确标注,能不能商用、能不能再分发都不确定。
  • 第三方扫描存在提醒项或未通过项,需要人工逐条确认。
  • 第三方目录整理,版本更新和行为细节以来源仓库为准。

适不适合你

更适合

  • 已经在用 Codex,想直接扩展它能力的人。
  • 需要处理开发类任务、又不想每次都手写提示词的人。

不太适合

  • 需要明确授权才能用到公司项目里的场景。
  • 需要厂商级技术支持和 SLA 的生产系统。

开发类 Skill 对比

6 个同类
Skill总安装GitHub 星权限许可证扫描
skill-vetter

技能审查员 · OpenClaw

8,779,018986操作浏览器MIT-0通过
ontology

本体论 · OpenClaw

6,636,960576只读MIT-0通过
entra-app-registration

内部应用程序注册 · Codex、Claude

6,631,872764接触敏感数据未明确通过
entra-app-registration

内部应用程序注册 · Codex、Claude

3,757,680201接触敏感数据未明确通过
nano-banana-pro

纳米香蕉专业版 · OpenClaw

3,526,898364接触敏感数据MIT-0有提醒
godot-save-load-systems

godot 保存加载系统 · 本页

3,442138可写文件未明确未通过

按安装量取同分类前几名;数字来自第三方目录统计,只作热度参考,不代表质量结论。

SKILL.md 原文

Save/Load Systems

JSON serialization, version migration, and PERSIST group patterns define robust data persistence.

NEVER Do

  • NEVER save without a version field — When you update your game's data structure, old saves will break. Always include a "version": "1.0.0" field and implement migration logic.
  • NEVER use absolute OS paths — Hardcoding C:/Users/... will break on every other machine. Always use the user:// protocol, which Godot maps to the correct OS-specific app data folder.
  • NEVER attempt to save Node references directly — Nodes are objects, not raw data. Extract the necessary primitive data (positions, health, levels) into a Dictionary or Resource instead.
  • NEVER forget to close FileAccess handles — Leaving a file open can lead to handle leaks and save-file corruption. In Godot 4, files auto-close when the variable goes out of scope, but explicit close() is safer for long-running logic.
  • NEVER use JSON for very large binary data — Storing 10MB of texture data as Base64 in JSON is slow and bloats file size. Use binary store_var() or separate dedicated asset files.
  • NEVER trust loaded data without validation — Users can edit save files. Always use data.get("field", default_value) and validate that numbers are within expected ranges to prevent crashes.
  • NEVER trigger a save during high-frequency physics or animation updates — A crash mid-write will corrupt the file. Save only on explicit game events like entering a menu, finishing a level, or at a checkpoint.
  • NEVER modify a save Dictionary while iterating over its keys — Calling erase() or add() inside a loop over the same dictionary causes iteration errors. Use data.duplicate() to iterate safely.
  • NEVER store raw passwords or sensitive credentials in unencrypted JSON — If you have sensitive data, use FileAccess.open_encrypted_with_pass() to secure it.
  • NEVER use ResourceLoader.load() for massive scenes on the main thread — It causes a visible freeze. Use ResourceLoader.load_threaded_request() to load levels in the background.
  • NEVER rely on get_instance_id() for cross-session identification — These IDs are assigned at runtime and change every time the game restarts. Generate your own persistent String UUIDs for game objects.
  • NEVER forget to call duplicate(true) on a loaded Resource stats block — If multiple enemies load the same "goblin_stats.tres", they will all share the same health pool unless duplicated.
  • NEVER use the "allow_objects" flag in store_var/get_var for untrusted data — Setting this to true allows full object decoding, which is a major security risk for saves downloaded from the web.
  • NEVER use JSON for data requiring strict type preservation — JSON converts Vector3 to a string or dictionary. For strict data types, use var_to_bytes() or a binary format.
  • NEVER leave internal metadata (set_meta) in persistent dictionaries — This unnecessarily inflates save file size. Clean your dictionaries before serialization.

Available Scripts

MANDATORY: Read the appropriate script before implementing the corresponding pattern.

save_load_patterns.gd

10 Expert patterns: PERSIST group serialization, binary snapshots, JSON safe-parsing, and threaded loading.

save_migration_manager.gd

Expert save file versioning with automatic migration between schema versions.

save_system_encryption.gd

AES-256 encrypted saves with compression to prevent casual save editing.


Pattern 1: JSON Save System (Recommended for Most Games)

Step 1: Create SaveManager AutoLoad
# save_manager.gd
extends Node

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

## Save data to JSON file
func save_game(data: Dictionary) -> void:
    var save_file := FileAccess.open(SAVE_PATH, FileAccess.WRITE)
    if save_file == null:
        push_error("Failed to open save file: " + str(FileAccess.get_open_error()))
        return

    var json_string := JSON.stringify(data, "\t")  # Pretty print
    save_file.store_line(json_string)
    save_file.close()
    print("Game saved successfully")

## Load data from JSON file
func load_game() -> Dictionary:
    if not FileAccess.file_exists(SAVE_PATH):
        push_warning("Save file does not exist")
        return {}

    var save_file := FileAccess.open(SAVE_PATH, FileAccess.READ)
    if save_file == null:
        push_error("Failed to open save file: " + str(FileAccess.get_open_error()))
        return {}

    var json_string := save_file.get_as_text()
    save_file.close()

    var json := JSON.new()
    var parse_result := json.parse(json_string)
    if parse_result != OK:
        push_error("JSON Parse Error: " + json.get_error_message())
        return {}

    return json.data as Dictionary

## Delete save file
func delete_save() -> void:
    if FileAccess.file_exists(SAVE_PATH):
        DirAccess.remove_absolute(SAVE_PATH)
        print("Save file deleted")
Step 2: Save Player Data
# player.gd
extends CharacterBody2D

var health: int = 100
var score: int = 0
var level: int = 1

func save_data() -> Dictionary:
    return {
        "health": health,
        "score": score,
        "level": level,
        "position": {
            "x": global_position.x,
            "y": global_position.y
        }
    }

func load_data(data: Dictionary) -> void:
    health = data.get("health", 100)
    score = data.get("score", 0)
    level = data.get("level", 1)
    if data.has("position"):
        global_position = Vector2(
            data.position.x,
            data.position.y
        )
Step 3: Trigger Save/Load
# game_manager.gd
extends Node

func save_game_state() -> void:
    var save_data := {
        "player": $Player.save_data(),
        "timestamp": Time.get_unix_time_from_system(),
        "version": "1.0.0"
    }
    SaveManager.save_game(save_data)

func load_game_state() -> void:
    var data := SaveManager.load_game()
    if data.is_empty():
        print("No save data found, starting new game")
        return

    if data.has("player"):
        $Player.load_data(data.player)

Pattern 2: Binary Save System (Advanced, Faster)

For large save files or when human-readability isn't needed:

const SAVE_PATH := "user://savegame.dat"

func save_game_binary(data: Dictionary) -> void:
    var save_file := FileAccess.open(SAVE_PATH, FileAccess.WRITE)
    if save_file == null:
        return

    save_file.store_var(data, true)  # true = full objects
    save_file.close()

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

    var save_file := FileAccess.open(SAVE_PATH, FileAccess.READ)
    if save_file == null:
        return {}

    var data: Dictionary = save_file.get_var(true)
    save_file.close()
    return data

Pattern 3: PERSIST Group Pattern

For auto-saving nodes with the persist group:

# Add nodes to "persist" group in editor or via code:
add_to_group("persist")

# Implement save/load in each persistent node:
func save() -> Dictionary:
    return {
        "filename": get_scene_file_path(),
        "parent": get_parent().get_path(),
        "pos_x": position.x,
        "pos_y": position.y,
        # ... other data
    }

func load(data: Dictionary) -> void:
    position = Vector2(data.pos_x, data.pos_y)
    # ... load other data

# SaveManager collects all persist nodes:
func save_all_persist_nodes() -> void:
    var save_nodes := get_tree().get_nodes_in_group("persist")
    var save_dict := {}

    for node in save_nodes:
        if not node.has_method("save"):
            continue
        save_dict[node.name] = node.save()

    save_game(save_dict)

Best Practices

1. Use user:// Protocol

# ✅ Good - platform-independent
const SAVE_PATH := "user://savegame.save"

# ❌ Bad - hardcoded path
const SAVE_PATH := "C:/Users/Player/savegame.save"

user:// paths:

  • Windows: %APPDATA%\Godot\app_userdata\[project_name]
  • macOS: ~/Library/Application Support/Godot/app_userdata/[project_name]
  • Linux: ~/.local/share/godot/app_userdata/[project_name]

2. Version Your Save Format

const SAVE_VERSION := "1.0.0"

func save_game(data: Dictionary) -> void:
    data["version"] = SAVE_VERSION
    # ... save logic

func load_game() -> Dictionary:
    var data := # ... load logic
    if data.get("version") != SAVE_VERSION:
        push_warning("Save version mismatch, migrating...")
        data = migrate_save_data(data)
    return data

3. Handle Errors Gracefully

func save_game(data: Dictionary) -> bool:
    var save_file := FileAccess.open(SAVE_PATH, FileAccess.WRITE)
    if save_file == null:
        var error := FileAccess.get_open_error()
        push_error("Save failed: " + error_string(error))
        return false

    save_file.store_line(JSON.stringify(data))
    save_file.close()
    return true

4. Auto-Save Pattern

var auto_save_timer: Timer

func _ready() -> void:
    # Auto-save every 5 minutes
    auto_save_timer = Timer.new()
    add_child(auto_save_timer)
    auto_save_timer.wait_time = 300.0
    auto_save_timer.timeout.connect(_on_auto_save)
    auto_save_timer.start()

func _on_auto_save() -> void:
    save_game_state()
    print("Auto-saved")

Testing Save Systems

func _ready() -> void:
    if OS.is_debug_build():
        test_save_load()

func test_save_load() -> void:
    var test_data := {"test_key": "test_value", "number": 42}
    save_game(test_data)
    var loaded := load_game()
    assert(loaded.test_key == "test_value")
    assert(loaded.number == 42)
    print("Save/Load test passed")

Common Gotchas

Issue: Saved Vector2/Vector3 not loading correctly

# ✅ Solution: Store as x, y, z components
"position": {"x": pos.x, "y": pos.y}

# Then reconstruct:
position = Vector2(data.position.x, data.position.y)

Issue: Resource paths not resolving

# ✅ Store resource paths as strings
"texture_path": texture.resource_path

# Then reload:
texture = load(data.texture_path)

Reference

Related

平台分布

Codex

40.41%
按下载量换算455

Claude

29.12%
按下载量换算328

Cursor

18.78%
按下载量换算211

Gemini CLI

9.28%
按下载量换算104

安全审计

Gen Agent Trust Hub

未通过

Socket

通过

Snyk

通过

权限和风险

可写文件

该 Skill 可能写入或修改本地文件,使用前需要确认目标目录和修改范围。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。来源安全扫描存在提醒或未通过项,安装前请自行复核。目前只有一个公开来源,建议同时核对源仓库。

继续浏览同类 Skills