【学習】Unity:アイテム所持とセーブ入門(第4回)― どこからでも使う:OwnedItemsData と Instance
第3回 までで、JSON + PlayerPrefs の考え方は揃いました。
しかしゲームのコードは、シーンのどこからでも「今の所持数」を触りたくなります。
- 敵を倒した
- 宝箱を開けた
- UI のボタンを押した
このとき 同じデータを共有したい。
今回は データ専用のクラスに Instance(教材では「入口が 1 つ」)を置くパターンを整理します。書籍サンプルでは OwnedItemsData がこの役です。
シリーズ
- 目次(00)
- 前回: 第3回
- 第4回(本記事):
OwnedItemsDataとInstance- 次回: 第5回:Item 取得からセーブまで
今日のゴール
- MonoBehaviour ではない「所持データ」の方が、保存と共有に向く理由が言える
Instanceに触れば同じオブジェクトを参照できる(教材レベルの理解)PlayerPrefs.HasKey… あればFromJson、なければnewが書けるSave()でJsonUtility.ToJson(this)→SetStringの流れを追える
なぜ MonoBehaviour から切り離す?
| 役割 | MonoBehaviour |
データ専用クラス |
|---|---|---|
| シーンに張り付く | 前提 | 不要 |
JsonUtility で丸ごと保存 |
罠になりやすい | 相性がよい |
| 「どこからでも触る」 | FindObjectOfType などが必要になりがち |
Instance で集約しやすい |
授業では 「JSON にしたい中身はデータ側に寄せる」 と決めると迷いが減ります。
OwnedItemsData の骨格(読み取りのポイント)
次の 4 点がわかれば、まずは十分です。
[Serializable]… JSON 化の前提Instance… 初回アクセスで 保存があれば復元/なければ新規List<OwnedItem> ownedItems… 第2回と同型の「集まり」Save()…JsonUtility.ToJson(this)で 自分全体を文字列化してPlayerPrefsへ
ざっくりした形(教材用・骨格イメージ)
using System;
using System.Linq;
using System.Collections.Generic;
using UnityEngine;
[Serializable]
public class OwnedItemsData
{
private const string PlayerPrefsKey = "OWNED_ITEMS_DATA";
public static OwnedItemsData Instance
{
get
{
if (_instance == null)
{
_instance = PlayerPrefs.HasKey(PlayerPrefsKey)
? JsonUtility.FromJson<OwnedItemsData>(PlayerPrefs.GetString(PlayerPrefsKey))
: new OwnedItemsData();
}
return _instance;
}
}
private static OwnedItemsData _instance;
[SerializeField] private List<OwnedItem> ownedItems = new List<OwnedItem>();
private OwnedItemsData() { }
public void Save()
{
string json = JsonUtility.ToJson(this);
PlayerPrefs.SetString(PlayerPrefsKey, json);
PlayerPrefs.Save();
}
// Add / Use / GetItem …(第2回の考え方と同じ)
}実装の詳細(OwnedItem のネスト、FirstOrDefault、Use で例外を投げる等)は、手元のサンプルや いきのこバトル:所持品データとオーディオ の全文と照らし合わせてください。
プログラムの流れ
ゲーム起動
↓
初めて Instance に触る
↓
セーブがあれば FromJson で復元/なければ new
↓
プレイ中に Add / Use
↓
タイミングを決めて Save()重要ポイント
privateコンストラクタ … 外部のnew OwnedItemsData()を減らし、生成ルートをInstanceに寄せる(教材としての狙い)- 保存キーは定数にまとめる(スペルミス防止)
- 毎フレーム
Saveは重い・壊れやすいので、授業では 取得直後・ステージクリア・メニュー閉じなど イベント単位を推奨
教材向けの一言
ここでこう言うと理解が進みます。
「JSON は、オブジェクトの状態を文字列にしたもの。だから保存したい状態は、まずデータのクラスに集約する」
発展アイデア
- OOP:シングルトンパターン と 本書の 3 パターン(純 C# /
DontDestroyOnLoad等)を比較する - テスト用に
DeleteAllとの付き合い方(開発ビルドだけ、など)を決める
次に進む
データの出入り口ができたので、フィールドのオブジェクトから Add して Save する流れをつなぎます。