セーブ機能は、保存できるだけでは完成ではありません。上書き前のバックアップ、形式変更への対応、破損検知、デバッグ表示までを一つの設計として追加します。
保存対象を辞書へまとめる
Playerから保存用の辞書を返し、統合版ではSaveManagerがConfigFileへ書き込みます。強化履歴と現在の能力値を混ぜず、どちらもロード時に復元できる形で保存します。保存先は端末ごとの「user://」を使い、プロジェクトフォルダへ直接書き込まないようにします。
次のコードは保存データの構成を示す概念例です。stats と upgrade_history は統合版にないため、このまま貼り付けるのではなく、プロジェクトで定義するか既存の能力値・強化データに置き換えてください。
func get_save_data() -> Dictionary:
return {
"level": level,
"experience": experience,
"stats": stats.duplicate(),
"upgrade_history": upgrade_history.duplicate(),
}
ロード時は保存データをPlayerへ適用し、ビルドボーナスをもう一度加算しないようにします。保存済みの現在値を復元するのか、履歴から再計算するのかを混ぜないことが重要です。
上書き前にバックアップを作る
既存ファイルを上書きする前に、現在のセーブをバックアップへコピーします。新しい形式を保存する場合はバージョン番号を持たせ、必要なら旧バージョンから移行する処理を用意します。統合版は一部の不足項目に初期値を使いますが、任意の旧形式を順番に移行する仕組みを保証するものではありません。移行できない未来のバージョンは、無理に読まずユーザーへ知らせます。
移行前のデータをバックアップしておくと、変換処理に問題があっても復元できます。復元ボタンにも確認ダイアログを置き、ユーザーが意図したスロットだけを戻すようにします。
SHA-256で破損を検知する
セーブ本体とは別のファイルへチェックサムを保存します。保存後に本体からSHA-256を計算し、読み込み前に再計算した値と比較します。一致しない場合はロードを止めてエラーを表示します。バックアップからの復元は別のボタンで行います。
チェックサムは暗号化ではありません。第三者による改ざんを完全に防ぐものではなく、途中でファイルが壊れたことを検知する仕組みです。統合版はチェックサムがない旧データを許容するため、その場合は整合性を検証できません。また本体とチェックサムは別々に書き込むため、中断時の不整合やバックアップの有効性を検証し、必要に応じて復元してください。
デバッグパネルで状態を見える化する
統合版のデバッグ表示では、現在のスロット、保存先、形式、直近の保存結果と各スロットの概要を確認できます。バックアップの有無やチェックサムの結果を表示するには追加実装が必要です。保存・読み込み処理から結果を記録しておくと、画面上で原因を追いやすくなります。リリース版ではデバッグパネルを隠します。
動作確認
- 保存した能力値と強化履歴が再起動後に一致する
- 上書き前にバックアップが作られる
- 不足項目に初期値を設定して読み込めるか、未対応の新形式は拒否されるかを確認する
- 本体を変更するとチェックサム不一致になる
- バックアップ復元後にチェックサムが作り直される
- デバッグUIをリリース版で表示しない
まとめ
保存データ、バックアップ、バージョン、チェックサム、デバッグ表示を別々の責務にすると、トラブル時に復旧しやすくなります。次は、これらの処理を自動テストし、結果を履歴へ残します。
統合版プロジェクトとの対応
この記事で扱う機能は、企画全体をまとめたauto_attack_final_verified.zipにも組み込んでいます。この記事のコードは段階的に追加するための説明なので、途中の記事と統合版全体のファイル構成は一致しない場合があります。
統合版には後続記事の機能も含まれます。記事の機能を確認するときは該当する操作を先に試し、最後にGodot 4.7でF5起動、入力、セーブ・ロード、再起動後の復元を確認してください。
