学習記事一覧 · Unity

【学習】Unity:アイテム所持とセーブ入門(第3回)― 消えないデータ:PlayerPrefs と JSON

第2回 までは、所持データは メモリ上だけにありました。

しかしゲームでは、よくこうなります。

アプリを終了しても、前回の続きから始めたい。

今回はその最小手段として PlayerPrefs と、複数アイテムを 1 本の文字列にまとめる JsonUtility を使います。

シリーズ


今日のゴール

  • PlayerPrefs.SetInt / GetInt数値 1 つが Play をまたいで残ることを確認する
  • アイテムが複数あると SetInt を量産しがちで辛い、という 問題意識 を持つ
  • クラス → JSON 文字列 → PlayerPrefs.SetString の流れを体験する
  • 初回起動(キーがまだない)ときの分岐を書ける

ステップ① PlayerPrefs で数値 1 つ

保存

void Start()
{
    PlayerPrefs.SetInt("Gold", 100);
    PlayerPrefs.Save();
}

読み込み

int gold = PlayerPrefs.GetInt("Gold");
Debug.Log(gold);

実験

  1. PlayStop → もう一度 Play
  2. 値が残ることを確認する(エディタ上の挙動は Project に依存するため、確実に学ぶなら実機ビルドも試すとよいです)

ステップ② 問題意識:アイテムは複数ある

例:

  • ポーション 3
  • 剣 1
  • 鍵 5

SetInt を種類の数だけ書くのは、管理が面倒キーが増えすぎます。


ステップ③ JSON でまとめる(イメージ)

テキストとして、たとえば次のような 1 塊にします(イメージ)。

{ "gold": 100 }

Unity では JsonUtilityクラスと JSON 文字列の相互変換を担当します。


ステップ④ 最小例:SaveData クラス

[System.Serializable]
public class SaveData
{
    public int gold;
}

保存

SaveData data = new SaveData();
data.gold = 100;
string json = JsonUtility.ToJson(data);
PlayerPrefs.SetString("SAVE_MIN", json);
PlayerPrefs.Save();

読み込み(初回ガード付き)

if (!PlayerPrefs.HasKey("SAVE_MIN"))
{
    Debug.Log("まだセーブがありません");
    return;
}
string json = PlayerPrefs.GetString("SAVE_MIN");
SaveData data = JsonUtility.FromJson<SaveData>(json);
Debug.Log(data.gold);

ステップ⑤ 第2回の ItemManager への載せ方(考え方)

やりたいことはシンプルです。

ownedItems のリスト全体」を JSON にして、1 つのキーに保存する」

string json = JsonUtility.ToJson(this); // MonoBehaviour なら this でも試せるが…
PlayerPrefs.SetString("ITEM_DATA", json);

授業では、まず SaveData のような普通のクラスで成功体験を作り、そのあと **「保存したいフィールドだけを持つクラス」**に寄せると安全です。

教材上の注意
MonoBehaviourFromJson完全復元するのは、授業の主役にしにくいです(コンポーネントはシーンにアタッチされるものだから)。
だから次回、データだけを持つクラスOwnedItemsData 型)に進みます。


重要ポイント

  • キー名(例:"SAVE_MIN")は 保存と読込で同じにする
  • [Serializable] を忘れると JSON 化できない/空になることがある
  • 初回はキーが無いHasKey で分岐する

プログラムの流れ

ゲーム中にデータが更新される

JsonUtility.ToJson で文字列化

PlayerPrefs.SetString で保存(必要なら Save)

次回起動で GetString → FromJson で復元

発展アイデア

  • セーブ直前に Debug.Log(json) で、中身の文字列を目で追う
  • エディタメニューで PlayerPrefs.DeleteAll() を叩き、初回動作を何度も試す

次に進む

データを MonoBehaviour から切り離しどこからでも同じ Instance で触れる形にすると、シーン設計が楽になります。

第4回:OwnedItemsDataInstance