Menu
CoddyTech

Загрузка и значения по умолчанию

Часть раздела Архитектура игр в Unity путешествия по Unity на Coddy. Урок 26 из 50.

Загрузка должна корректно обрабатывать отсутствующие или неполные сохранения. Гоночная игра сохраняет RaceSave; во второй версии игры добавили 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 вернул бы начальные значения полей класса.

challenge icon

Задание

Средне

Виртуальный питомец загружает pet.json при запуске игры, а клавиша Space кормит питомца и сохраняет его. При загрузке возникают две проблемы:

  • У нового игрока нет файла pet.json, и метод Start завершается с исключением FileNotFoundException. Если файла нет, оставьте питомца с настройками из Inspector (Biscuit, hunger 30, happiness 80, Ball) и выведите в журнал A new pet: Biscuit.
  • Версия 1 игры сохраняла только petName и hunger; happiness и toys появились в версии 2 (см. PetSave.cs). При загрузке старого сохранения с помощью FromJson свойства получают значения 50 и пустой список игрушек из класса, а не значения из Inspector. Загрузите существующий файл в pet с помощью JsonUtility.FromJsonOverwrite, чтобы поля, отсутствующие в файле, сохранили значения из Inspector, и выведите приветствие с загруженным именем, например Welcome back, Mochi.

Нажмите Играть и покормите питомца, затем нажмите Стоп и снова Играть, а затем нажмите Проверить.

Попробуйте сами

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 iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

Все уроки раздела Архитектура игр в Unity