Unityのセーブ機能は、保存場所・保存方式・復元処理の3つに分けて考えましょう。図で全体像をつかみ、必要な手順から確認できます。

先に要点

  • ファイル保存先の確認には Application.persistentDataPath を使います。
  • Windowsでは通常、ユーザーフォルダー内の AppData/LocalLow 以下です。
  • PlayerPrefsは別の仕組みで保存されるため、同じフォルダーにJSONファイルができるわけではありません。
  • バイナリ化・圧縮・暗号化は別の処理です。形式だけで改ざんを防げるとは限りません。

Unity 6.0の公式資料などをもとに解説します。OS・Unityのバージョンによる違いは、実行する環境で確認してください。

Unityのセーブデータはどこに保存される?

Application.persistentDataPath で、終了後も残すファイルの保存先を取得できます。パスの取得だけでは保存されません。別途、ファイルを書き込みます。

Windowsの保存場所を開く方法

保存先の見取り図Windowsでは、ここから探す
① エクスプローラーのアドレスバーへ入力
%USERPROFILE%\AppData\LocalLow
② Company Name のフォルダーUnityのPlayer設定にある会社名
③ Product Name のフォルダーUnityのPlayer設定にある製品名
一般化した説明図です。実際のフォルダー名はアプリにより異なります。
見つからなければ、下のコードで実際の保存先を確認。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で行いましょう。

セーブ・ロードとは?シーン保存との違い

セーブ・ロードの全体像終了しても、続きから遊べる仕組み
1保存する進行状況を
端末へ書き込む
2終了するアプリを閉じる
保存した値は残る
3再起動する保存した値を
読み込む準備
4ロード・反映読み込んだ値を
ゲームの状態へ戻す
保存データの例 ステージ:3 / コイン:120
再起動後も同じ状態に戻るか確認します。
読み込むだけでは、画面やキャラクターは変わりません。
読み込んだ値をオブジェクトやUIへ反映する処理も必要です。

Unityエディタでのシーン保存とは別の機能です。シーン間だけのデータ保持なら、ファイル保存が不要な場合もあります。SceneManagerによるシーン切り替えとデータ保持も参考にしてください。

PlayerPrefs・JSON・バイナリの使い分け

保存方式の選び方まずは「何を残したいか」で選ぶ
保存したいものは?
音量・表示など、少量の設定PlayerPrefsint / float / string
手軽に扱える設定値向け。
機密情報は保存しない。
進行状況・所持品をまとめたい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でできたら、配布先の端末でも同じ手順を試しておくことが大切です。