Menu
CoddyTech

Das Spiel speichern

Teil des Abschnitts Spielarchitektur in Unity der Unity-Journey von Coddy. Lektion 31 von 64.

Ein Spielstand ist ein Objekt, das als JSON geschrieben wird. Packe alles, was der Spielstand benötigt, in eine [System.Serializable]-Klasse, fülle sie mit den Daten aus dem Spiel und schreibe JsonUtility.ToJson davon an einen Ort, der das Spiel überdauert. Dieser Dungeon speichert den Boden, das Gold und die gefundenen Schlüssel:

[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 ist ein Ordner, den Unity dem Spiel auf jeder Plattform bereitstellt und der zwischen Spielstarts und auch bei Updates erhalten bleibt. Path.Combine verbindet den Ordner und einen Dateinamen mit dem Trennzeichen der jeweiligen Plattform. File.WriteAllText(path, text) schreibt die Datei und ersetzt dabei eine alte Datei, File.Exists gibt an, ob eine Datei vorhanden ist, und File.ReadAllText liest sie wieder ein (alle drei stammen aus System.IO). Der Ordner des Spiels selbst kann schreibgeschützt sein. Speichere Spielstände deshalb in persistentDataPath und nirgendwo sonst. Erstelle den Pfad in Awake oder Start: Unity erlaubt persistentDataPath nicht in einem Feldinitialisierer.

Die Spielstandklasse enthält nur, was der Spielstand benötigt. Zum Speichern kopiert das Spiel Werte in die Klasse, zum Laden kopiert es Werte daraus. Ein kleiner Spielstand kann statt in einer Datei auch in PlayerPrefs gespeichert werden: PlayerPrefs.SetString("dungeon", json) und PlayerPrefs.GetString("dungeon") speichern denselben JSON-Inhalt. Speichere, wenn etwas Wichtiges passiert, an einem Kontrollpunkt oder über eine Schaltfläche zum Speichern: OnApplicationQuit wird bei einem normalen Beenden ausgeführt, aber ein Smartphone kann ein Spiel im Hintergrund schließen, ohne dass diese Methode ausgeführt wird.

challenge icon

Aufgabe

Mittel

Speichere die Insel in island.json.

  1. Schreibe in IslandSave.cs eine Klasse [System.Serializable] namens IslandSave mit public Vector3 playerPosition; und public List<Vector3> flags;.
  2. Setze in Start() path auf Path.Combine(Application.persistentDataPath, "island.json").
  3. Save() schreibt ein IslandSave mit transform.position und flags als JSON in path.
  4. Start() liest eine vorhandene Datei wieder ein: die Position und PlantFlag für jede Flagge.

Drücke Spielen, platziere Flaggen, drücke Speichern, stoppe und drücke auf „Spielen“: Sie sind wieder da. Drücke dann auf „Prüfen“.

Probier es selbst

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");
        // Lade hier 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);
    }

    // Die Schaltfläche Save ruft dies auf
    public void Save()
    {
        // Schreibe die Position des Spielers und die Flaggen in island.json
    }
}

Alle Lektionen in Spielarchitektur in Unity

Übe selbstständig: Unity-Playground