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.
Aufgabe
MittelSpeichere die Insel in island.json.
- Schreibe in
IslandSave.cseine Klasse[System.Serializable]namensIslandSavemitpublic Vector3 playerPosition;undpublic List<Vector3> flags;. - Setze in
Start()pathaufPath.Combine(Application.persistentDataPath, "island.json"). Save()schreibt ein IslandSave mittransform.positionundflagsals JSON inpath.Start()liest eine vorhandene Datei wieder ein: die Position undPlantFlagfü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
1Komponenten statt Hierarchien
Kleine KomponentenEin Basis-GegnerskriptAbstrakte KomponentenZusammenwirkende KomponentenRückblick: Modulares GeschützRückblick: Zwillingskanone4Serialisierte Daten
Serialisierbare KlassenListen im InspectorEnums im InspectorRückblick: Loot-TabelleRückblick: Beute auswürfeln2Schnittstellen in Unity
IDamageableSchnittstellen und TryGetComponentGetComponentsZusammenfassung: InteraktionstasteZusammenfassung: Nächstes in Reichweite5ScriptableObjects
Daten-AssetsWaffenwerteGemeinsame EinstellungenDen Wind speichernWellen als DatenRückblick: Item-DatenbankRückblick: Im Shop einkaufen8Wiederverwendbarer Code
ErweiterungsmethodenEin generisches SingletonGenerische HilfsmethodenRückblick: FindNearestÜbe selbstständig: Unity-Playground