Unity Save System について
Unity Save System は、Unity 6+ のゲーム開発者向けにセーブシステムの実装方法を案内するスキルです。基本的な設定保存からローカルとクラウドの併用まで扱い、アトミック書き込みやデータのバージョン管理を重視します。
主な機能
- 01ゲーム状態のシリアライズと永続化
- 02アトミックなファイル書き込みとバックアップ復旧
- 03セーブのバージョン管理と移行
- 04複数スロットと自動保存
- 05UGS クラウドセーブと任意の暗号化
活用シーン
- 01Unity ゲームの進行状況保存の実装
- 02セーブ形式変更後のデータ移行
- 03一時停止やシーン変更時の自動保存
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ juliankerignard/ unity-skills --skill unity-save-systemインストール後、Claude Code で/unity-save-systemを入力して読み込まれたか確認します。
同梱ファイルreferences/save-advanced.mdreferences/save-templates.md
詳細
Unity Save System
このスキルでできること
Unity 6+ 向けの完全なセーブシステムの実装を支援します。ゲーム状態のシリアライズ、アトミック書き込みによるファイル永続化、セーブデータのバージョン管理、複数スロットの管理、自動セーブ、クラウドセーブ(UGS)、オプションの暗号化を扱います。シンプルな PlayerPrefs からローカル/クラウドのハイブリッドアーキテクチャまでを対象とします。
前提条件
- Unity 6.0+(Awaitable API)
- 推奨:高度なシリアライズには Newtonsoft.Json(
com.unity.nuget.newtonsoft-json) - シンプルな用途では必須の依存関係はありません(JsonUtility で十分です)
クイックスタート
- フォーマットを選択:JsonUtility(シンプル)または Newtonsoft.Json(ポリモーフィズム、Dictionary)
- 保存する各コンポーネントに
ISaveableインターフェースを作成 Application.persistentDataPathへのアトミック書き込みを行うSaveManagerを実装- 自動セーブを接続(dirty flag + timer +
OnApplicationPause) - EditMode テストでセーブ/ロードのサイクルをテスト(
/unity-testを参照)
判断フローチャート
Que sauvegarder ?
|
+-- Preferences utilisateur (volume, langue, bindings) ?
| +-- Peu de donnees (<1 KB) --> PlayerPrefs
| +-- Plus structure ----------> JSON dans persistentDataPath
|
+-- Etat de jeu (progression, inventaire, position) ?
| +-- Slot unique -----------> JSON + ISaveable pattern
| +-- Multi-slots -----------> SaveManager avec index + slots nommes
| +-- Donnees volumineuses (>10 MB) --> Format binaire (MemoryPack/MessagePack)
|
+-- Cloud sync ?
| +-- Unity Gaming Services --> UGS Cloud Save
| +-- Cross-platform natif --> Platform Toolkit (Unity 6.3+)
| +-- Hybride (local + cloud) -> ISaveStorage abstraction (voir `references/save-advanced.md`)
|
+-- Sensible (anti-cheat) ?
+-- Encryption AES + hash d'integrite (voir `references/save-advanced.md`)
ステップごとのガイド
ステップ 1 — シリアライズ形式を選択する
| 基準 | JsonUtility | Newtonsoft.Json | MemoryPack | MessagePack |
|---|---|---|---|---|
| セットアップ | Unity に含まれる | Unity パッケージ | NuGet | NuGet |
| ポリモーフィズム | いいえ | はい(TypeNameHandling) | はい | はい |
| Dictionary | いいえ | はい | はい | はい |
| 可読性 | JSON | JSON | バイナリ | バイナリ |
| パフォーマンス | 高速 | 中程度 | 非常に高速 | 高速 |
| サイズ | 中程度 | 中程度 | 小さい | 小さい |
| 推奨用途 | プロトタイピング | デフォルトで推奨 | 10 MB を超えるデータ | バイナリ形式の代替 |
ステップ 2 — ISaveable と SaveData を作成する
ISaveableを定義します:SaveKey、CaptureState()、RestoreState(object)versionフィールド、Dictionary<string, object>、メタデータを含むSaveDataを作成します- 完全なコード(ISaveable、SaveData、SaveManager)は
references/save-templates.mdを参照してください
ステップ 3 — SaveManager を実装する
- シングルトンまたはサービスロケータのパターンを使用します(
/unityのアーキテクチャを参照) ISaveableのレジストリ(Register/Unregister)SaveAsync:すべての状態をキャプチャ -> シリアライズ -> アトミック書き込み(.tmp -> .save、.bak)LoadAsync:ファイルを読み込む -> デシリアライズ -> すべての状態を復元- パス:
Path.Combine(Application.persistentDataPath, "saves", slotName + ".save")
ステップ 4 — 自動セーブ
- Dirty flag:各
ISaveableが変更を通知します - 設定可能なタイマー(デフォルトは 60~120 秒)
OnApplicationPause(true)とシーン変更時にセーブします- 自動セーブについては
references/save-advanced.mdのセクション「Auto-Save」を参照してください
ステップ 5 — セーブ/ロードのサイクルをテストする
- EditMode テスト:セーブ -> 状態をクリア -> ロード -> 状態が復元されたことをアサート
- 破損テスト:切り詰められたファイルをロード -> .bak へのフォールバックを確認
- 移行テスト:v2 のコードで v1 のセーブをロード
厳守事項
必ず行うこと
- 必ずアトミック書き込みを使用します(.tmp に書き込み、rename し、.bak を保持)
- 必ず
SaveDataのバージョンを管理します(スキーマが変更されるたびにversionフィールドを増やします) - 必ず
Application.persistentDataPathを使用します(dataPathやstreamingAssetsPathは使用しません) - 必ずモバイルでは
OnApplicationPause(true)時にセーブします - 必ず POCO(Plain Old C# Objects)をシリアライズします — Unity の型は使用しません
- 必ず「セーブデータがない」場合(初回起動)に対処します
絶対に行わないこと
- 絶対に
BinaryFormatterを使用しません — 既知のセキュリティ上の脆弱性があり、非推奨です - 絶対に
MonoBehaviour、GameObject、ScriptableObjectの参照をセーブデータに保存しません - 絶対に 100 KB を超えるファイルをメインスレッドで同期的にセーブしません
- 絶対に新しいファイルの書き込みが完了する前に古いファイルを削除しません(クラッシュ時に確実に破損します)
- 絶対に I/O 例外を無視しません — 必ず try/catch とフォールバックを実装します
関連スキル
/unity-code-gen— ISaveable と SaveManager のボイラープレートを生成する/unity-test— 保存/読み込みサイクルを検証する EditMode テスト/unity-debug— デシリアライズの問題を診断する/addressables— アセット参照を address 文字列で保存する
トラブルシューティング
| 問題 | 考えられる原因 | 解決策 |
|---|---|---|
読み込み時の FileNotFoundException | 初回起動で、セーブデータがない | 読み込み前に File.Exists() を確認し、デフォルトデータを返す |
| アップデート後にデータが失われる | スキーマの変更にマイグレーションがない | version フィールドと、v1->v2->vN のマイグレーション処理を追加する |
JsonSerializationException | ポリモーフィック型が認識されない | Newtonsoft:TypeNameHandling.Auto とカスタム SerializationBinder を使用する |
| セーブデータが破損している(JSON が途中で切れている) | 書き込み中にクラッシュした | アトミック書き込み(.tmp -> rename)と .bak へのフォールバックを行う |
UnauthorizedAccessException | 許可されていないパス(Android のスコープ) | persistentDataPath のみを使用する |
| PlayerPrefs が消える(iOS) | システムによるクリーンアップ、または再インストール | 重要なデータはファイルに移行する |
| セーブデータが大きすぎる(>50 MB) | 大量のデータを JSON にシリアライズしている | MemoryPack/MessagePack に切り替え、圧縮(GZip)する |
| クラウド/ローカル間で同期がずれる | バージョンの競合 | 競合解決(タイムスタンプまたはバージョンカウンター)を実装する |
コメント
Markdown 対応