ゲームを終了しても、ハイスコアや設定、進み具合は覚えておいてほしいですよね。普通の変数は、ゲームを終了すると消えてしまいます。今回は、Unityでデータを保存する2つの方法、手軽なPlayerPrefsと、まとまったデータを保存できるJSONをご紹介します!
この記事で学べること
- PlayerPrefsで数値や文字列を保存・読み込みする方法
- PlayerPrefsが向いているもの・向いていないもの
- JsonUtilityで、クラスのデータをJSONの文字列にする方法
- JSONをファイルに保存・読み込みする方法(Application.persistentDataPath)
前提知識
- 変数でデータを保存しよう
- メソッドを作ろう:処理に名前を付けてまとめる
- 入力系のUIを作ろう:InputField・Slider・Toggle・Dropdown:設定画面でPlayerPrefsを少し使っています
2つの保存方法
| 方法 | 向いているもの | 向いていないもの |
|---|---|---|
| PlayerPrefs | ハイスコア、音量、最後に選んだステージなどの少ない値 | たくさんのデータ、アイテムの一覧、なくなると困るデータ |
| JSON+ファイル | セーブデータ(レベル、所持金、アイテムの一覧など) | ―(少し書く量が増える) |
PlayerPrefs:手軽に値を保存する
保存と読み込み
using UnityEngine;
public class SaveHighScoreExample : MonoBehaviour
{
private const string HighScoreKey = "HighScore";
void Start()
{
// 読み込み。まだ保存されていなければ、2つ目の値(0)が返る
int highScore = PlayerPrefs.GetInt(HighScoreKey, 0);
Debug.Log("前回のハイスコア: " + highScore);
}
// スコアが決まったときに呼ぶ
public void SubmitScore(int score)
{
int highScore = PlayerPrefs.GetInt(HighScoreKey, 0);
if (score > highScore)
{
PlayerPrefs.SetInt(HighScoreKey, score);
PlayerPrefs.Save();
Debug.Log("ハイスコア更新! " + score);
}
}
}
- 保存:
PlayerPrefs.SetInt(キー, 値)、SetFloat、SetString - 読み込み:
PlayerPrefs.GetInt(キー, 保存されていないときの値)、GetFloat、GetString - キー:保存する値の名前。保存と読み込みで同じ文字列を使うので、上のように
constで1か所にまとめておくと、つづり間違いを防げます - PlayerPrefs.Save():すぐに書き込む。ゲームを普通に終了したときも自動で保存されますが、強制終了に備えて大事なタイミングで呼んでおくと安心です
そのほかの便利なメソッド
| 書き方 | 内容 |
|---|---|
PlayerPrefs.HasKey(キー) | そのキーが保存されているか(true/false) |
PlayerPrefs.DeleteKey(キー) | そのキーを消す |
PlayerPrefs.DeleteAll() | 全部消す(テストでやり直したいときに) |
エディタでテストしたデータを消したいときは、上部メニューのEdit>Clear All PlayerPrefsでも全部消せます。
どこに保存される?
PlayerPrefsは、パソコンやスマホの中の、Unityが決めた場所に保存されます。
- Windows:レジストリ(ファイルとしては見えない場所)
- Mac:~/Library/Preferences の中のファイル
- Web:ブラウザの保存領域
プロジェクトのフォルダには保存されないので、Assetsを見ても出てきません。保存場所はProject SettingsのPlayerにあるCompany NameとProduct Nameで決まるので、あとから変えると前のデータが読めなくなります。
PlayerPrefsに向いていないもの
- たくさんのデータ:アイテムの一覧など。キーがどんどん増えて管理できなくなります
- なくなると困るデータ:ユーザーが簡単に中身を書き換えたり消したりできます
- 複雑なデータ:int・float・stringの3種類しか保存できません
こういうデータは、次のJSONを使いましょう。
スライムPlayerPrefsに全部入れていたら、キーの名前が何十個にもなって訳が分からなくなった・・・



まとまったデータはクラスにまとめてJSONで保存するとスッキリするよ!次の節を見てみてね
JSON:まとまったデータをファイルに保存する
JSONとは
JSONは、データを文字で表す書き方の1つです。例えばこんな形です。
{"playerName":"勇者","level":5,"gold":120,"items":["やくそう","どうのつるぎ"]}
UnityではJsonUtilityを使うと、クラスのデータとJSONの文字列を簡単に行き来できます。JSONについてもっと詳しく知りたい人は、Jsonデータについて+Unityで使うJsonUtilityも読んでみてください。
保存したいデータをクラスにまとめる
using System.Collections.Generic;
[System.Serializable]
public class SaveGameData
{
public string playerName = "勇者";
public int level = 1;
public int gold = 0;
public List<string> items = new List<string>();
}
[System.Serializable]を付けると、JsonUtilityで変換できるようになります- 変換されるのはpublicの変数(または[SerializeField]を付けた変数)です
- このクラスはMonoBehaviourではないので、ゲームオブジェクトにアタッチはしません。1つのファイル「SaveGameData.cs」として作っておきます
ファイルに保存・読み込みする
using System.IO;
using UnityEngine;
public class SaveGameManager : MonoBehaviour
{
private string SavePath => Path.Combine(Application.persistentDataPath, "savedata.json");
private SaveGameData data;
void Start()
{
data = Load();
Debug.Log(data.playerName + " レベル" + data.level + " 所持金" + data.gold);
// 試しにデータを変えて保存してみる
data.level++;
data.gold += 50;
data.items.Add("やくそう");
Save();
}
public void Save()
{
// クラスのデータ → JSONの文字列 → ファイル
string json = JsonUtility.ToJson(data, true);
File.WriteAllText(SavePath, json);
Debug.Log("保存しました: " + SavePath);
}
private SaveGameData Load()
{
// ファイルがまだない(初めて遊ぶ)ときは、新しいデータを使う
if (!File.Exists(SavePath))
{
return new SaveGameData();
}
// ファイル → JSONの文字列 → クラスのデータ
string json = File.ReadAllText(SavePath);
return JsonUtility.FromJson<SaveGameData>(json);
}
}
空のゲームオブジェクトにアタッチして、何回か再生してみてください。再生するたびにレベルと所持金が増えていけば、ちゃんと保存と読み込みが出来ています。
ポイント
JsonUtility.ToJson(データ, true):クラスをJSONの文字列にする。2つ目をtrueにすると、改行付きの読みやすい形になりますJsonUtility.FromJson<型>(文字列):JSONの文字列をクラスに戻すApplication.persistentDataPath:アプリがデータを保存してよい場所。WindowsでもMacでもスマホでも、それぞれに合った場所になりますPath.Combine:フォルダとファイル名を、OSに合った区切り文字でつなげるFile.Exists:初めて遊ぶときはファイルがないので、先に確認してから読み込みますusing System.IO;が必要です
保存したファイルを見てみる
ログに出た保存先のフォルダを開くと、savedata.jsonがあります。メモ帳などで開くと、JSONの中身を確認出来ます。
ファイルは普通のテキストなので、ユーザーが書き換えることも出来ます。ランキングなど、ずるをされると困るデータには、別の仕組み(サーバーでの保存など)が必要です。
よくあるエラーと対処法
エラー:保存したはずなのに、読み込むと最初の値のまま
- 原因:PlayerPrefsのキーのつづりが、保存と読み込みで違う。またはJSONにしたいクラスに
[System.Serializable]が付いていない、変数がprivateになっている - 対処法:キーは
constで1か所にまとめる。クラスに[System.Serializable]を付け、保存したい変数はpublicにする
エラー:The name ‘File’ does not exist in the current context
- 原因:
using System.IO;を書いていない - 対処法:スクリプトの一番上に足す
エラー:FileNotFoundException
- 原因:まだ保存していないファイルを読み込もうとした
- 対処法:
File.Existsで確認してから読み込む
エラー:ArgumentException: JSON parse error
- 原因:JSONのファイルの中身が壊れている(手で書き換えて形がおかしくなったなど)
- 対処法:ファイルを消してやり直す。手で書き換えるときは、カッコや「,」の対応に注意する
まとめ
- PlayerPrefs:少ない値(ハイスコア、音量など)を手軽に保存。
SetInt/GetInt(キー, 既定値) - 大事なデータ、たくさんのデータはJSON+ファイル
[System.Serializable]のクラス →JsonUtility.ToJson→File.WriteAllText- 保存先は
Application.persistentDataPath。読み込む前にFile.Existsで確認
セーブ機能をもっと作り込みたい人は、データ保存!UnityでSave/Load機能を実装しよう!基礎編も参考にしてください。
コメント