Загрузка и значения по умолчанию
Часть раздела Архитектура игр в 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 вернул бы начальные значения полей класса.
Задание
СреднеВиртуальный питомец загружает 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;
}
}
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Архитектура игр в Unity
1Компоненты, а не иерархии
Небольшие компонентыБазовый скрипт врагаАбстрактные компонентыСовместная работа компонентовПовторение: модульная турель4Сериализованные данные
Сериализуемые классыСписки в InspectorПеречисления в InspectorПовторение: таблица лута2Интерфейсы в Unity
IDamageableИнтерфейсы и TryGetComponentGetComponentsПовторение: клавиша взаимодействия5ScriptableObjects
Ресурсы данныхХарактеристики оружияОбщие настройкиВолны как данныеПовторение: база предметов3События
События C# в UnityПодписка в OnEnableПоля UnityEventСобытия управляют интерфейсомПовторение: всплывающее окно достижения6Сохранение с помощью JSON
JsonUtilityСохранение игрыЗагрузка и значения по умолчаниюПовторение: слоты сохранения