godot-save-load-systems について
Godot のゲーム向けセーブ・ロードシステムを設計するスキルです。形式の選択から、バージョン管理、検証、安全な保存手順まで扱い、移行・暗号化・整合性確認用のスクリプトも含みます。
主な機能
- 01JSON、バイナリ、Resource の永続化形式
- 02バージョン管理とセーブ移行
- 03バックアップ、整合性検証、安全な書き込み
- 04暗号化セーブとデータ検証
- 05PERSIST グループによる自動収集
活用シーン
- 01新作ゲームのセーブ形式設計
- 02セーブ構造の変更と旧データ移行
- 03ユーザー編集可能なセーブの検証
- 04機密フィールドや大きなデータの保存
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ thedivergentai/ game-dev-agentic-skills --skill godot-save-load-systemsインストール後、Claude Code で/godot-save-load-systemsを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/migration-notes.mdsave-patterns-deep.mdscripts/save_integrity_validator.gdsave_load_patterns.gdsave_migration_manager.gdsave_system_encryption.gd詳細
絶対にしてはいけないこと
- バージョンフィールドを指定せずに保存しないでください — ゲームのデータ構造を更新すると、古いセーブデータが使えなくなります。必ず
"version": "1.0.0"フィールドを含め、移行ロジックを実装してください。 - OS の絶対パスを使用しないでください —
C:/Users/...をハードコードすると、ほかのすべてのマシンで動作しなくなります。Godot が OS ごとに適切なアプリデータフォルダーへ割り当てるuser://プロトコルを必ず使用してください。 - Node の参照を直接保存しようとしないでください — Node はオブジェクトであり、生のデータではありません。必要なプリミティブデータ(位置、体力、レベルなど)を
DictionaryまたはResourceに取り出してください。 - FileAccess ハンドルを閉じ忘れないでください — ファイルを開いたままにすると、ハンドルリークやセーブファイルの破損につながる可能性があります。Godot 4 では変数のスコープを抜けるとファイルは自動的に閉じられますが、長時間実行されるロジックでは明示的に
close()を呼び出すほうが安全です。 - 非常に大きなバイナリデータに JSON を使用しないでください — 10MB のテクスチャデータを Base64 として JSON に保存すると処理が遅くなり、ファイルサイズも膨らみます。バイナリの
store_var()または専用のアセットファイルを使用してください。 - 読み込んだデータを検証せずに信用しないでください — ユーザーはセーブファイルを編集できます。クラッシュを防ぐため、必ず
data.get("field", default_value)を使用し、数値が想定範囲内にあるか検証してください。 - 高頻度の物理演算やアニメーションの更新中に保存を実行しないでください — 書き込みの途中でクラッシュすると、ファイルが破損します。メニューへの移動、レベルのクリア、チェックポイント到達など、明示的なゲームイベントでのみ保存してください。
- キーを反復処理している間にセーブ用の Dictionary を変更しないでください — 同じ Dictionary のループ内で
erase()またはadd()を呼び出すと、反復処理エラーが発生します。安全に反復処理するにはdata.duplicate()を使用してください。 - 暗号化されていない JSON にパスワードや機密性の高い認証情報を保存しないでください — 機密データがある場合は、保護するために
FileAccess.open_encrypted_with_pass()を使用してください。 - メインスレッドで大規模なシーンの読み込みに ResourceLoader.load() を使用しないでください — 画面が目に見えてフリーズします。バックグラウンドでレベルを読み込むには
ResourceLoader.load_threaded_request()を使用してください。 - セッションをまたぐ識別に get_instance_id() を使用しないでください — これらの ID は実行時に割り当てられ、ゲームを再起動するたびに変わります。ゲームオブジェクトには、独自の永続的な
StringUUID を生成してください。 - 読み込んだ Resource のステータスブロックに duplicate(true) を呼び出し忘れないでください — 複数の敵が同じ「goblin_stats.tres」を読み込むと、複製しない限り全員が同じ体力プールを共有します。
- 信頼できないデータに store_var/get_var の「allow_objects」フラグを使用しないでください — これを
trueに設定するとオブジェクトの完全なデコードが許可され、ウェブからダウンロードしたセーブデータに対する重大なセキュリティリスクとなります。 - 厳密な型の保持が必要なデータに JSON を使用しないでください — JSON は
Vector3を文字列または辞書に変換します。厳密なデータ型にはvar_to_bytes()またはバイナリ形式を使用してください。 - 内部メタデータ(set_meta)を永続化する Dictionary に残さないでください — セーブファイルのサイズが不必要に大きくなります。シリアライズの前に Dictionary を整理してください。
利用可能なスクリプト
必須:SaveManager のコードを書く前に、選択した形式に対応するスクリプトを読んでください。
save_load_patterns.gd
JSON / binary / PERSIST collect では必須です — パターンのデフォルトは store_var(..., false) です。
save_migration_manager.gd
ビルドより古い可能性のある version フィールドを持つセーブデータでは必須です。
save_system_encryption.gd
暗号化スロットを使う前に必須です — パスワードは安全なストレージまたはユーザーシークレットから取得し、サンプルにハードコードしないでください。
save_integrity_validator.gd
ローリング .bak と SHA-256 による検証で、スロットを信用する前に確認します。不一致の場合はバックアップにフォールバックします。
詳細解説(必要に応じて読み込む)
JSON/PERSIST の手順解説、バイナリの例、注意点、上級者向けの暗号化パスでは必須です — references/save-patterns-deep.md。Step 1~3 の Autoload チュートリアルをシーンに貼り付けないでください。
専門家向けの重要事項
CAUTION: ベースラインのチュートリアルでは
store_var(data, true)を使用していました。信頼できないuser://のセーブでは、allow_objects=falseにしてください。MOD/ワークショップのファイルによる RCE のリスクがあります。
- JSON 内のベクター —
{x,y,z}の各成分を保存します。JSON ではVector3を忠実に往復変換できません。 - ローリングバックアップ — 書き込み中にクラッシュするとプライマリファイルが破損します。上書き前に
.bakにコピーしてください(save_integrity_validator.gd)。 - 保存するタイミング — メニュー/チェックポイント/レベルクリア時のみです。物理フレームごとの保存は避けてください。
決定ツリー:永続化形式を選ぶ
| 必要なもの | 形式 | 必須 |
|---|---|---|
| 人間が読みやすい、小〜中規模の進行状況 | JSON + version | save_load_patterns.gd |
| 型を忠実に保持する Variant/大きなデータ塊 | allow_objects=false にしたバイナリ store_var | 同上 |
| 型付き Resource ツリー/インスペクターのスキーマ | ResourceSaver / .tres/.res | 関連項目 godot-resource-data-patterns |
| 多数のシーンノードを自動収集 | PERSIST グループ + save()/load() | save_load_patterns.gd |
| スキーマが変更された | 移行してからロード | save_migration_manager.gd |
| 改ざん防止/機密フィールド | 暗号化された FileAccess | save_system_encryption.gd |
ここに Step 1〜3 の JSON Autoload チュートリアルを貼り付けないでください。スクリプトを使って実装します。
allow_objects の信頼境界
デフォルトでは必ず store_var(data, false) / get_var(false) を使用します。
| ケース | allow_objects | ルール |
|---|---|---|
プレイヤーの user:// セーブ、ワークショップの MOD、ダウンロード | false | true は絶対に使用しないでください。RCE のリスクがあります |
| 信頼できるローカル環境のみ(自分のツール、管理下のオフラインデバッグ用フィクスチャ) | 避けられない場合のみ true | 理由を記載してください。デフォルトとしてリリースしないでください。Resource またはプリミティブ型の Dictionary を優先してください |
暗号化された上級者向けの経路でも、ペイロードが明示的に信頼できるローカル環境のもので、ユーザーが編集できない場合を除き、false を使用します。
ゴールデンパス(バージョン → 移行 → バックアップ → アトミック書き込み)
- バージョンフィールド — すべてのセーブデータに設定します。
- 移行 — バージョンが異なる場合は save_migration_manager.gd を使って移行します。
- バックアップ — 上書き前に既存ファイルを
.bakにコピーします(DirAccess.copy_absolute)。 - 書き込み — 一時ファイルに書き込んでから名前を変更するか、バックアップ後に書き込みます。オープンエラーを検証してください。
- 整合性(任意) —
FileAccess.get_sha256で比較し、不一致の場合はバックアップにフォールバックします。 - パス —
user://のみを使用します。絶対 OS パスは使用しないでください。 - 保存するタイミング — メニュー、チェックポイント、レベルクリア時です。物理フレームごとの保存は避けてください。
設定には、進行状況の JSON/バイナリとは別に ConfigFile を使用できます。
リファレンス
段階的な情報開示:特定の API を調べる場合にのみ公式ドキュメントへのリンクを開き、関連分野へ案内する場合にのみ関連スキルを読み込んでください。スキル群全体を事前に読み込まないでください。
公式ドキュメント
- ゲームの保存 — このスキルの基盤となる、グループの永続化シリアライズ、JSON ライン形式、標準的なセーブ/ロードの流れについて説明します。
- Godot のファイルパス — OS ごとのアプリデータフォルダーにおける
user://とres://の対応関係を説明します。絶対パスをハードコードしないでください。 - バイナリーシリアライズ API —
store_var/get_varによる Variant のエンコード、型の忠実性、信頼できないセーブデータでallow_objectsが安全でない理由について説明します。 - バックグラウンド読み込み — セーブデータの復元後にレベルやリソースを引っ掛かりなく読み込むための
ResourceLoader.load_threaded_requestについて説明します。 - ファイルシステム — ファイルの存在確認、バックアップ、安全な上書きパターンにおける FileAccess/DirAccess のワークフローについて説明します。
- リソース — Resource と Dictionary による永続化、
duplicate(true)、独自実装の JSON より.tres/.resが適しているケースについて説明します。 - グループ — Persist/PERSIST の自動収集パターンで使用する SceneTree のグループメンバーシップについて説明します。
- FileAccess — オープンモード、パスワード付き暗号化の AES ヘルパー、SHA-256、圧縮フラグ、バッファー I/O について説明します。
- JSON — 人が読みやすいセーブデータや、解析エラーの検証に使用する
stringify/parse/parse_stringについて説明します。 - ConfigFile — ゲーム状態全体のセーブデータとは別に管理する、INI 形式の設定(
user://settings.cfg)について説明します。 - ResourceSaver — JSON による型情報の損失が許容できない場合に、型付き Resource/カスタム Resource ツリーを永続化する方法について説明します。
- AESContext — 独自の圧縮・暗号化セーブパイプラインで使用する、低レベルの AES ブロック暗号化/復号について説明します。
関連スキル
前提条件
- godot-project-foundations — SaveManager がパスを管理する前に、ProjectSettings、Autoload の登録、
user://のプロジェクト ID が存在している必要があります。 - godot-gdscript-mastery — バージョン管理されたシリアライズ/デシリアライズコードのための、型付き Dictionary、Resource、エラー処理のパターンについて説明します。
- godot-autoload-architecture — SaveManager はほぼ常に Autoload です。シングルトンの管理、起動順序、シーン変更後も状態を維持する方法には、こちらを使用してください。
補完
- godot-resource-data-patterns — すべてを JSON に平坦化する代わりに ResourceSaver と組み合わせる、カスタム Resource スキーマと
.tresワークフローです。 - godot-scene-management — スレッドを使ったシーン切り替えと、ロード後に Persist ノードを破棄・再構築して古いワールド状態を残さない方法です。
- godot-signal-architecture — UI やシステムが SaveManager に直接依存せずに反応できる、
game_saved/game_loadedイベントバスです。 - godot-ui-containers — このスキルがゲーム進行状況とは別に永続化する ConfigFile/音量キーを書き込む設定メニューです。
- godot-inventory-system — アイテムスタックと装備の辞書は、最も大きな Persist ペイロードになります。セーブデータのマイグレーションでは ID 方式を共有してください。
- godot-quest-system — クエストフラグ/ステージ ID は、ジャーナル UI を壊さずにバージョン管理されたセーブデータとの間で往復できる必要があります。
- godot-economy-system — 通貨ウォレットとショップのアンロックには、プレイヤーの進行状況と同じバージョンフィールドと検証が必要です。
下流/利用側
- godot-adapt-single-to-multiplayer — ローカルのセーブパターンはホスト権威型の状態同期に変わります。マルチプレイヤーでは、クライアントが編集した JSON を決して信用しないでください。
- godot-monte-carlo-balancer — セーブデータに保存された進行状況/経済の曲線を、マイグレーション時のデフォルト値に照らしてシミュレーションし、バランス調整する場合に使用します。
- godot-multiplayer-networking — 対戦モードで平文の
user://セーブデータに代わる、サーバー側の検証とスナップショット形式です。
マスター
- godot-master — ライブラリのルーター兼ミラー化されたモジュールのエントリです。永続化とコンテンツシステムのどちらを担当するドメインスキルかを調べるときに開いてください。