Menu
CoddyTech

Сохранение игры

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

Сохранение игры — это один объект, записанный в формате JSON. Помести всё необходимое для сохранения в класс [System.Serializable], заполни его данными из игры и запиши результат JsonUtility.ToJson в место, которое сохраняется после завершения игры. В этом подземелье сохраняются этаж, золото и найденные ключи:

[System.Serializable]
public class DungeonSave
{
    public int floor;
    public int gold;
    public List<string> keys;
}
using System.Collections.Generic;
using System.IO;
using UnityEngine;

public class Dungeon : MonoBehaviour
{
    public int floor = 1;
    public int gold;
    public List<string> keys = new List<string>();
    private string path;

    void Start()
    {
        path = Path.Combine(Application.persistentDataPath, "dungeon.json");
        if (File.Exists(path))
        {
            DungeonSave save = JsonUtility.FromJson<DungeonSave>(File.ReadAllText(path));
            floor = save.floor;
            gold = save.gold;
            keys = save.keys;
        }
    }

    public void Save()
    {
        DungeonSave save = new DungeonSave();
        save.floor = floor;
        save.gold = gold;
        save.keys = keys;
        File.WriteAllText(path, JsonUtility.ToJson(save));
    }
}

Application.persistentDataPath — это папка, которую Unity предоставляет игре на каждой платформе; она сохраняется между запусками игры и при обновлениях. Path.Combine соединяет её с именем файла, используя разделитель, принятый на платформе. File.WriteAllText(path, text) записывает файл, заменяя старый, File.Exists сообщает, существует ли такой файл, а File.ReadAllText считывает его содержимое (все три метода — из System.IO). Папка самой игры может быть доступна только для чтения, поэтому сохранения помещаются в persistentDataPath и никуда больше. Создавай путь в Awake или Start: Unity не разрешает использовать persistentDataPath при инициализации поля.

Класс сохранения содержит только то, что нужно сохранить, а игра копирует в него значения для сохранения и из него — для загрузки. Небольшое сохранение можно поместить в PlayerPrefs вместо файла: PlayerPrefs.SetString("dungeon", json) и PlayerPrefs.GetString("dungeon") хранят тот же JSON. Сохраняй игру, когда происходит что-то важное, на контрольной точке или с помощью кнопки сохранения: OnApplicationQuit выполняется при обычном выходе, но телефон может закрыть игру в фоновом режиме без вызова этого метода.

challenge icon

Задание

Средне

Исследователь ходит по острову с помощью стрелок, а клавиша Space устанавливает флаг там, где стоит исследователь. Сохраните игру на острове в файле island.json:

  • В IslandSave.cs напишите класс [System.Serializable] IslandSave с открытыми полями playerPosition (типа Vector3) и flags (типа List<Vector3>).
  • Метод Save(), который вызывает кнопка Save, записывает позицию исследователя и флаги в формате JSON в файл island.json в Application.persistentDataPath.
  • В Start(), если существует island.json, верните исследователя в сохранённую позицию и снова установите все сохранённые флаги с помощью PlantFlag, чтобы флаги попали в список для следующего сохранения.

Нажмите Play, установите несколько флагов и нажмите Save, затем нажмите Stop и снова Play. После этого нажмите Check.

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

using System.Collections.Generic;
using System.IO;
using UnityEngine;
using UnityEngine.InputSystem;

public class Explorer : MonoBehaviour
{
    public GameObject flagPrefab;
    public float speed = 4f;
    private List<Vector3> flags = new List<Vector3>();
    private InputAction moveAction;

    void Start()
    {
        moveAction = InputSystem.actions.FindAction("Move");
        // Загрузите island.json здесь
    }

    void Update()
    {
        Vector2 input = moveAction.ReadValue<Vector2>();
        transform.Translate(new Vector3(input.x, 0f, input.y) * speed * Time.deltaTime);
        if (Keyboard.current.spaceKey.wasPressedThisFrame)
        {
            PlantFlag(transform.position);
        }
    }

    void PlantFlag(Vector3 position)
    {
        flags.Add(position);
        Instantiate(flagPrefab, new Vector3(position.x, 0.5f, position.z), Quaternion.identity);
    }

    // Кнопка Save вызывает этот метод
    public void Save()
    {
        // Запишите позицию игрока и флаги в island.json
    }
}
quiz iconПроверьте себя

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

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