Menu
CoddyTech

Guardar la partida

Parte de la sección Arquitectura de juegos en Unity del Journey de Unity de Coddy. Lección 25 de 50.

Una partida guardada es un objeto escrito como JSON. Pon todo lo que necesite la partida en una clase [System.Serializable], rellénala con datos del juego y escribe JsonUtility.ToJson en algún lugar que perdure más que la partida. Esta mazmorra guarda el piso, el oro y las llaves encontradas:

[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 es una carpeta que Unity proporciona al juego en todas las plataformas, que se conserva entre partidas y durante las actualizaciones. Path.Combine une esta ruta y un nombre de archivo con el separador de la plataforma. File.WriteAllText(path, text) escribe el archivo y reemplaza uno antiguo, File.Exists indica si existe uno y File.ReadAllText lo lee (los tres son de System.IO). Es posible que la carpeta propia del juego sea de solo lectura, así que las partidas guardadas deben ir en persistentDataPath y en ningún otro lugar. Crea la ruta en Awake o Start: Unity no permite usar persistentDataPath en un inicializador de campo.

La clase de guardado contiene solo lo que necesita la partida guardada, y el juego copia valores en ella para guardar y los copia desde ella para cargar. Una partida guardada pequeña puede almacenarse en PlayerPrefs en lugar de en un archivo: PlayerPrefs.SetString("dungeon", json) y PlayerPrefs.GetString("dungeon") guardan el mismo JSON. Guarda cuando ocurra algo que valga la pena conservar, en un punto de control o con un botón Guardar: OnApplicationQuit se ejecuta al salir normalmente, pero un teléfono puede cerrar una partida en segundo plano sin ejecutarlo.

challenge icon

Desafío

Intermedio

El explorador recorre la isla con las flechas, y la barra espaciadora planta una bandera donde se encuentra el explorador. Guarda la isla como una partida en el archivo island.json:

  • En IslandSave.cs, escribe una clase [System.Serializable] llamada IslandSave con los campos públicos playerPosition (un Vector3) y flags (una List<Vector3>).
  • Save(), que ejecuta el botón Save, escribe la posición del explorador y las banderas como JSON en island.json, en Application.persistentDataPath.
  • En Start(), si existe island.json, devuelve al explorador a la posición guardada y vuelve a plantar todas las banderas guardadas con PlantFlag, para que las banderas estén en la lista para el próximo guardado.

Pulsa Play, planta algunas banderas y haz clic en Save; después, pulsa Stop y Play de nuevo. Después, pulsa Check.

Pruébalo tú mismo

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");
        // Carga island.json aquí
    }

    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);
    }

    // El botón Save llama a este método
    public void Save()
    {
        // Escribe la posición del jugador y las banderas en island.json
    }
}
quiz iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de Arquitectura de juegos en Unity