Menu
CoddyTech

Load and Defaults

Part of the Game Architecture in Unity section of Coddy's Unity journey. Lesson 26 of 50.

Loading has to cope with saves that are not there or not complete. A racing game saves a RaceSave; version 2 of the game added 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();
}

A new player has no file, and File.ReadAllText on a missing file throws FileNotFoundException, so check File.Exists first and start from new RaceSave(): 0 trophies, the Rookie Kart and volume 0.8, the field initializers. An old player's version 1 file holds {"trophies":3,"car":"Red Racer"}. FromJson makes a new RaceSave, which runs the field initializers, and then sets only the keys the JSON has, so musicVolume is 0.8. A key the class has no field for is ignored. A new version of the game can therefore read old saves, as long as every new field has an initializer with a sensible value.

JsonUtility.FromJsonOverwrite(json, obj) fills an object that already exists instead of making one, and leaves every field the JSON lacks as it was. FromJson cannot make a MonoBehaviour or a ScriptableObject (Unity throws Cannot deserialize JSON to new instances of type 'RaceSettings.'), so a settings asset is loaded by overwriting it: JsonUtility.FromJsonOverwrite(json, settings);. Overwriting also keeps the values an object already holds, such as the ones the Inspector gave it, where FromJson would bring back the class's initializers.

challenge icon

Challenge

Medium

The virtual pet loads pet.json when the game starts, and Space feeds the pet and saves it. Loading goes wrong in two ways:

  • A new player has no pet.json, and Start stops with a FileNotFoundException. Without a file, keep the pet the Inspector set up (Biscuit, hunger 30, happiness 80, a Ball) and log A new pet: Biscuit.
  • Version 1 of the game saved only petName and hunger; happiness and toys came in version 2 (see PetSave.cs). An old save loaded with FromJson gets the class's 50 and no toys, not the Inspector's values. Load an existing file into pet with JsonUtility.FromJsonOverwrite, so whatever the file lacks keeps the Inspector's value, and log the welcome with the loaded name, as Welcome back, Mochi.

Press Play and feed the pet, then Stop and Play again, then Check.

Try it yourself

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;
    }
}
quiz iconTest yourself

This lesson includes a short quiz. Start the lesson to answer it and track your progress.

All lessons in Game Architecture in Unity