Menu
CoddyTech

Das Spiel speichern

Teil des Abschnitts Spielarchitektur in Unity der Unity-Journey von Coddy. Lektion 25 von 50.

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 Spieldaten und schreibe JsonUtility.ToJson davon an einen Ort, der das Spiel überdauert. Dieser Dungeon speichert den Stock, 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 über Updates hinweg erhalten bleibt. Path.Combine verbindet ihn mit einem Dateinamen und verwendet dabei das Trennzeichen der Plattform. File.WriteAllText(path, text) schreibt die Datei und ersetzt dabei eine vorhandene 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 ist möglicherweise schreibgeschützt. Speichere Spielstände daher in persistentDataPath und nirgendwo sonst. Erstelle den Pfad in Awake oder Start: Unity erlaubt persistentDataPath nicht in einem Feldinitialisierer.

Die Spielstandklasse enthält nur das, was der Spielstand benötigt, und das Spiel kopiert zum Speichern Werte hinein und zum Laden wieder heraus. Ein kleiner Spielstand kann statt in einer Datei auch in PlayerPrefs gespeichert werden: PlayerPrefs.SetString("dungeon", json) und PlayerPrefs.GetString("dungeon") speichern dieselben JSON-Daten. Speichere, wenn etwas passiert, das es wert ist, festgehalten zu werden, an einem Kontrollpunkt oder über eine Speichern-Schaltfläche: OnApplicationQuit wird bei einem normalen Beenden ausgeführt, aber ein Smartphone kann ein Spiel im Hintergrund schließen, ohne dass dies geschieht.

challenge icon

Aufgabe

Mittel

Der Explorer läuft mit den Pfeiltasten über die Insel, und mit der Leertaste wird dort eine Flagge gesetzt, wo der Explorer steht. Mache aus der Insel ein gespeichertes Spiel in der Datei island.json:

  • Schreibe in IslandSave.cs eine Klasse [System.Serializable] namens IslandSave mit den öffentlichen Feldern playerPosition (ein Vector3) und flags (eine List<Vector3>).
  • Save(), das von der Schaltfläche Save aufgerufen wird, schreibt die Position des Explorers und die Flaggen als JSON nach island.json in Application.persistentDataPath.
  • Wenn island.json existiert, setze den Explorer in Start() an die gespeicherte Position zurück und setze jede gespeicherte Flagge erneut, und zwar mit PlantFlag, damit die Flaggen für den nächsten Speichervorgang in der Liste stehen.

Drücke Play, setze ein paar Flaggen und klicke auf Save, dann auf Stop und erneut auf Play. Klicke anschließend auf Check.

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 island.json hier
    }

    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
    }
}
quiz iconTeste dich selbst

Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.

Alle Lektionen in Spielarchitektur in Unity