読み込みとデフォルト値
CoddyのUnityジャーニー「Unityにおけるゲームアーキテクチャ」セクションの一部。レッスン 26/50。
読み込みでは、存在しないセーブや不完全なセーブにも対処する必要があります。レースゲームはRaceSaveを保存します。ゲームのバージョン2ではmusicVolumeが追加されました。
[System.Serializable]
public class RaceSave
{
public int trophies;
public string car = "Rookie Kart";
public float musicVolume = 0.8f;
}RaceSave save;
if (File.Exists(path))
{
save = JsonUtility.FromJson<RaceSave>(File.ReadAllText(path));
}
else
{
save = new RaceSave();
}新しいプレイヤーにはファイルがありません。存在しないファイルに対してFile.ReadAllTextを呼び出すとFileNotFoundExceptionがスローされるため、まずFile.Existsを確認し、new RaceSave()から始めます。つまり、トロフィーは0個、車はRookie Kart、音量は0.8で、これらはフィールド初期化子の値です。以前からのプレイヤーのバージョン1のファイルには{"trophies":3,"car":"Red Racer"}が格納されています。FromJsonは新しいRaceSaveを作成し、フィールド初期化子を実行してから、JSONにあるキーだけを設定するため、musicVolumeは0.8になります。クラスに対応するフィールドがないキーは無視されます。したがって、新しいフィールドすべてに妥当な値の初期化子があれば、ゲームの新しいバージョンでも古いセーブを読み込めます。
JsonUtility.FromJsonOverwrite(json, obj)はオブジェクトを新しく作成する代わりに、すでに存在するオブジェクトに値を設定し、JSONにないフィールドはそのままにします。FromJsonではMonoBehaviourやScriptableObjectを作成できないため(UnityはCannot deserialize JSON to new instances of type 'RaceSettings.'をスローします)、設定アセットは上書きして読み込みます。JsonUtility.FromJsonOverwrite(json, settings);。上書きでは、Inspectorで設定された値など、オブジェクトがすでに持っている値も保持されます。一方、FromJsonではクラスの初期化子の値に戻ります。
チャレンジ
中級バーチャルペットはゲームの開始時にpet.jsonを読み込み、Spaceキーを押すとペットに餌を与えて保存します。読み込みには2つの問題があります。
- 新しいプレイヤーは
pet.jsonを持っておらず、StartでFileNotFoundExceptionが発生して停止します。ファイルがない場合は、Inspectorで設定したペット(Biscuit、空腹度30、幸福度80、Ball)をそのまま使い、A new pet: Biscuitとログに出力してください。 - ゲームのバージョン1では
petNameとhungerだけが保存され、happinessとtoysはバージョン2で追加されました(PetSave.csを参照)。古いセーブデータをFromJsonで読み込むと、Inspectorの値ではなく、クラスの既定値である50とおもちゃなしになります。既存のファイルをJsonUtility.FromJsonOverwriteでpetに読み込み、ファイルに含まれていない値はInspectorの値のままになるようにし、読み込んだ名前を使って、Welcome back, Mochiのように歓迎メッセージをログに出力してください。
Playを押してペットに餌を与え、次にStopを押してからもう一度Playを押し、その後Checkを押してください。
自分で試してみよう
using System.IO;
using UnityEngine;
using UnityEngine.InputSystem;
using TMPro;
public class PetCare : MonoBehaviour
{
public PetSave pet;
public TMP_Text petText;
private string path;
void Start()
{
path = Path.Combine(Application.persistentDataPath, "pet.json");
pet = JsonUtility.FromJson<PetSave>(File.ReadAllText(path));
Show();
}
void Update()
{
if (Keyboard.current.spaceKey.wasPressedThisFrame)
{
pet.hunger = Mathf.Max(pet.hunger - 10, 0);
pet.happiness = Mathf.Min(pet.happiness + 5, 100);
File.WriteAllText(path, JsonUtility.ToJson(pet));
Show();
}
}
void Show()
{
petText.text = pet.petName + ": hunger " + pet.hunger + ", happiness " + pet.happiness;
}
}
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。