Unityのセーブデータの保存場所と作り方|PlayerPrefs・JSONの使い分け
Unityのセーブ機能は、保存場所・保存方式・復元処理の3つに分けて考えましょう。図で全体像をつかみ、必要な手順から確認できます。
先に要点
- ファイル保存先の確認には Application.persistentDataPath を使います。
- Windowsでは通常、ユーザーフォルダー内の AppData/LocalLow 以下です。
- PlayerPrefsは別の仕組みで保存されるため、同じフォルダーにJSONファイルができるわけではありません。
- バイナリ化・圧縮・暗号化は別の処理です。形式だけで改ざんを防げるとは限りません。
Unity 6.0の公式資料などをもとに解説します。OS・Unityのバージョンによる違いは、実行する環境で確認してください。
Unityのセーブデータはどこに保存される?
Application.persistentDataPath で、終了後も残すファイルの保存先を取得できます。パスの取得だけでは保存されません。別途、ファイルを書き込みます。
Windowsの保存場所を開く方法
%USERPROFILE%\AppData\LocalLow
見つからなければ、下のコードで実際の保存先を確認。PlayerPrefsは別の場所に保存されます。
Company Name・Product NameはProject SettingsのPlayer設定と照合します。配布ゲームは保存方式が異なる場合があるため、そのゲームの公式案内も確認してください。
Mac・iOS・Android・Webの保存先
| 環境 | persistentDataPathの代表例・確認点 |
|---|---|
| Windows Editor/Player | %USERPROFILE%/AppData/LocalLow/会社名/製品名 |
| macOS Editor | ~/Library/Application Support/会社名/製品名 |
| macOS Player | ~/Library/Application Support/unity.会社名.製品名。Editor用の場所が存在する場合はそちらが使われます。 |
| iOS | /var/mobile/Containers/Data/Application/<guid>/Documents |
| Android | 多くの端末では /storage/emulated/<userid>/Android/data/<packagename>/files |
| Web(WebGL) | ブラウザーのIndexedDBに対応する仮想ファイルシステム。WindowsのLocalLowとは異なります。 |
表は代表例です。保存処理では固定パスではなくAPIの戻り値を使います。macOSはFinderの「移動」→「フォルダへ移動」で確認できます。モバイルの保存先は、PCから直接開けるとは限りません。
参考:Unity公式:Application.persistentDataPath
自作ゲームの実際の保存先をConsoleへ表示する
SavePathLogger.cs を作成 → 有効なGameObjectに追加 → Playの順で実行します。Consoleに出るのは実行環境のパスです。スマートフォンの保存先は実機で確認してください。
using UnityEngine;
public class SavePathLogger : MonoBehaviour
{
private void Start()
{
Debug.Log("セーブ用フォルダー: " + Application.persistentDataPath);
}
}保存先とファイル名は Path.Combine で組み合わせます。save.json などの名前は自分で決めるもので、Unity共通の名前ではありません。
PlayerPrefsの保存先はファイル保存と別
WindowsのPlayerPrefsは通常、レジストリへ保存されます。ビルドしたゲームは HKEY_CURRENT_USER\Software\会社名\製品名、EditorのPlay Modeは HKEY_CURRENT_USER\Software\Unity\UnityEditor\会社名\製品名 が対応する場所です。
見つからないときの注意
PlayerPrefsを探す場所と、JSONファイルを探す場所は別です。初期化はレジストリの直接編集ではなく、PlayerPrefs.DeleteKey など対象を限定できるAPIで行いましょう。
セーブ・ロードとは?シーン保存との違い
端末へ書き込む
保存した値は残る
読み込む準備
ゲームの状態へ戻す
再起動後も同じ状態に戻るか確認します。
読み込んだ値をオブジェクトやUIへ反映する処理も必要です。
Unityエディタでのシーン保存とは別の機能です。シーン間だけのデータ保持なら、ファイル保存が不要な場合もあります。SceneManagerによるシーン切り替えとデータ保持も参考にしてください。
PlayerPrefs・JSON・バイナリの使い分け
機密情報は保存しない。
ファイルへの読み書きは別途必要。
内容は編集できるため保護も別設計。
バイナリも検討。ただし、型・順序・バージョンの管理が必要です。
PlayerPrefsは小さな設定値に使えますが、パスワードや認証情報には使わないでください。Unity公式のPlayerPrefs説明でも暗号化されないことが明記されています。
セーブデータの作り方:保存・読み込み・削除の流れ
1. 保存する値とデータ構造を決める
保存するのは「ステージ番号」「コイン数」など、復元に必要な数値やIDです。GameObjectを丸ごと保存しようとせず、ロード後に値を戻す設計から始めましょう。
Transformは必要な位置・回転・大きさの値を保存します。将来の形式変更に備え、保存用クラスに version を持たせる方法もあります。
2. 少量の設定をPlayerPrefsで保存する
BGM音量を扱うメソッド内の処理例です。保存はボタン操作時、読み込みは起動時など、分けて呼び出します。
// 保存ボタンなどから呼ぶ処理
PlayerPrefs.SetFloat("Example.BgmVolume", 0.5f);
PlayerPrefs.Save();
// 起動時などに呼ぶ処理(未保存なら1.0f)
float volume = PlayerPrefs.GetFloat("Example.BgmVolume", 1.0f);読み込んだ volume をAudioSourceやUIへ反映する処理も必要です。詳しくはPlayerPrefsで保存・読み込み・削除する方法で解説しています。
3. 進行状況はJSONへ変換してファイルに保存する
- 保存したいフィールドを持つクラスを作り、[System.Serializable] を付ける。
- 現在のゲーム状態を保存用データへ移す。
- JsonUtility.ToJson でJSON文字列へ変換する。
- Path.Combine で保存パスを作り、File.WriteAllText などで書き込む。
- ロード時はファイルの有無を確認し、File.ReadAllText と JsonUtility.FromJson<保存用クラス> で戻す。
- 値が妥当か確認してから、ゲームの進行状況やUIへ反映する。
JsonUtilityは変換の機能であり、それだけでファイルを作成する機能ではありません。また、対象はUnityのシリアル化ルールに従うフィールドです。プロパティや Dictionary はそのまま扱えず、配列だけを直接渡す場合もクラスなどで包む必要があります。
実装例はJsonUtilityを使った保存・読み込みへ。対応する型の制約はUnity公式のJSONシリアル化を確認してください。
4. 削除・初期化は保存方式ごとに行う
| 対象 | 削除の方法 | 削除後にすること |
|---|---|---|
| PlayerPrefsの特定の設定 | PlayerPrefs.DeleteKey(“Example.BgmVolume”) の後に PlayerPrefs.Save() | 必要ならメモリ上の値やUIも初期値へ戻す。 |
| 自分で作成したJSON/バイナリファイル | 対象ファイルを確認し、File.Delete(対象パス) で削除 | ファイルがない場合の初期データを用意する。 |
削除前の注意
PlayerPrefs.DeleteAll()は、そのアプリのPlayerPrefs全体を削除します。 JSONファイルだけを消す操作とは異なります。必要なデータは先にバックアップし、特定のセーブを消したいときはキーやファイルを限定してください。
保存できない・ロードすると初期値になるとき
| 症状 | 確認すること |
|---|---|
| ファイルが見つからない | 保存処理を実行したか。書き込み先と読み込み先のパス・ファイル名が一致しているか。 |
| Editorでは読めるがビルド版で読めない | 実行環境やPlayer設定の違いを確認する。PlayerPrefsとファイルの保存先を混同しない。 |
| JSONが空、必要な値が入らない | Serializable属性、フィールドの宣言、対応型を確認する。 |
| ロード後も画面やキャラクターが変わらない | 読み込んだ値を実際のオブジェクト・UIへ反映しているか。 |
| 毎回最初からになる | 起動時に初期データを保存し、前回のデータを上書きしていないか。 |
| 例外が出る・保存が途中で失敗する | Consoleのエラー内容、空き容量、パス、権限を確認する。失敗した保存を成功扱いにしない。 |
本番向けには、保存中の終了に備えた一時ファイルと置換、バックアップ、形式のバージョン管理、例外処理も検討します。置換の対応状況・挙動は対象環境で確認してください。
読み込みに失敗したファイルを、すぐ初期データで上書きしないでください。 破損・形式違い・権限不足などの原因を確認し、元ファイルを残して復旧できるようにします。
バイナリ・Base64・暗号化を混同しない
バイナリ保存は、値をバイト列として決めた形式で書き込む方法です。BinaryWriter/BinaryReaderを使う場合は、書いた型と順序に合わせて読み込みます。バイナリ形式の保存・読み込みの記事で基本を確認できます。
安全性についての重要な区別
バイナリ化やBase64化だけでは、暗号化にも改ざん防止にもなりません。
- 圧縮:データのサイズを小さくする処理。
- 暗号化:鍵を使って内容を読みにくくする処理。
- 改ざん検知:変更されていないか確認する仕組み。暗号化とは別に設計する。
読みにくいファイル=安全なファイルではありません。.dat や .bin の拡張子でも暗号化の有無は分かりません。不正変更が問題になる重要な判定は、サーバー側での検証も検討します。
なお、BinaryWriterとBinaryFormatterは別物です。BinaryFormatterは安全でないため、新しい保存実装に採用しないでください。参考:MicrosoftのBinaryFormatterセキュリティガイド。
クラウド保存とEasy Save 3を検討する場合
ローカル保存だけでは別の端末へ引き継げない
persistentDataPathは端末内の保存先です。別端末への引き継ぎは自動ではありません。クラウドとの送受信、ユーザー識別、競合の処理が必要です。
SQLはデータベースを操作するための言語で、単独のクラウド同期サービスではありません。サービスやサーバーの選定と、端末内の保存形式の選定は分けて考えましょう。
Easy Save 3は保存処理を補助する選択肢
実装を減らしたい場合は、有料アセットのEasy Save 3も選択肢です。対応するGameObjectやTransformを扱えますが、保存対象・参照関係の設定と、ロード後の確認は必要です。
私が個人開発で初めて購入した有料アセットで、データ管理に使用しています。導入手順や基本操作はEasy Save 3の使い方、対応型は開発元の公式資料を確認してください。
よくある質問
Unityのセーブデータは、すべてLocalLowにありますか?
いいえ。WindowsでpersistentDataPathを使う場合の代表的な保存先です。PlayerPrefs、独自指定のフォルダー、クラウドなど、ゲームごとの実装によって変わります。
Playを停止するとセーブデータも消えますか?
シーン上の変更が戻ることと、ファイルやPlayerPrefsへ書き込んだデータが消えることは別です。Play中に保存したデータが残る場合があるので、試験用のキー・ファイル名を分けて管理しましょう。
保存ファイルがない初回起動はどうすればいいですか?
ファイルがない場合は初期データを用意し、ゲームを開始できるようにします。ただし「初回でファイルがない」と「既存ファイルを読み込めない」は分けて扱います。後者を無条件に初回扱いすると、復旧できるデータを失う原因になります。
まとめ:保存場所・方式・復元処理を分けて考える
- 保存先を調べるときは、まずpersistentDataPathと実際に使っている保存方式を確認する。
- 少量の設定はPlayerPrefs、まとまった進行状況はJSONなど、用途に合わせて選ぶ。
- 保存・読み込みだけでなく、ゲームへの反映、削除範囲、失敗時の扱いも決める。
- バイナリ・圧縮・暗号化は別物。形式だけで安全性を判断しない。
最初は保存する項目を少なくして、保存→終了→再起動→ロードの一連の流れを確認しましょう。PCでできたら、配布先の端末でも同じ手順を試しておくことが大切です。
サイトアイコン-2-150x150.png)