In diesem Lernprogramm erfahren Sie, wie Sie ein einfaches System zum Erstellen und Verwalten von Spielständen für Ihre Unity-Spiele implementieren. Wir werden den Rahmen für eine Final Fantasy-Wie das Hauptmenü ermöglicht es Spielern, neue, einzigartige Speicherdateien zu erstellen und vorhandene zu laden. Die aufgezeigten Prinzipien ermöglichen es Ihnen, sie auf die Bedürfnisse Ihres Spiels auszudehnen.
Am Ende des Tutorials haben Sie gelernt, wie Sie:
Hinweis: Dieser Ansatz zum Speichern und Laden von Spieldaten funktioniert auf allen Plattformen außer für den Web Player. Informationen zum Speichern von Spieldaten im Web Player finden Sie in den offiziellen Dokumenten zu Unity Web Player und zur Browserkommunikation.
Als Erstes erstellen wir einen Code, mit dem wir unsere Spieldaten serialisieren können, dh sie in ein Format konvertieren, das gespeichert und später wiederhergestellt werden kann. Dazu erstellen wir ein C # -Skript und rufen es auf SaveLoad
. Dieses Skript übernimmt alle Speicher- und Ladefunktionen.
Wir werden dieses Skript aus anderen Skripten referenzieren, also machen wir es zu einer statischen Klasse, indem wir das Wort hinzufügen statisch
zwischen Öffentlichkeit
und Klasse
. Lassen Sie uns auch die entfernen : MonoBehaviour
Teil, weil wir es nicht an eine GameObject
. Und da erbt es nicht mehr von MonoBehaviour
, lass uns das löschen Start
und Aktualisieren
Funktionen.
Der resultierende Code sollte folgendermaßen aussehen:
mit UnityEngine; using System.Collections; öffentliche statische Klasse SaveLoad
Nun wollen wir diesem Skript einige neue Funktionen hinzufügen, also unmittelbar unter dem Wortlaut using System.Collections;
, Folgendes hinzufügen:
using System.Collections.Generic; using System.Runtime.Serialization.Formatters.Binary; using System.IO;
In der ersten Zeile können wir dynamische Listen in C # verwenden, dies ist jedoch für die Serialisierung nicht erforderlich. Die zweite Zeile ermöglicht es uns, die Serialisierungsfunktionen des Betriebssystems innerhalb des Skripts zu verwenden. In der dritten Zeile, IO
steht für Input-Output, und ermöglicht es uns, auf unseren Computer oder unser mobiles Gerät zu schreiben und zu lesen. Mit anderen Worten: Mit dieser Zeile können wir eindeutige Dateien erstellen und diese später lesen.
Wir können jetzt einige Daten serialisieren!
Jetzt, da unser Skript die Fähigkeit zur Serialisierung besitzt, müssen wir einige Klassen einrichten, die serialisiert werden sollen. Wenn Sie über ein einfaches RPG nachdenken, z Final Fantasy, Es bietet Spielern die Möglichkeit, verschiedene gespeicherte Spiele zu erstellen und zu laden. Erstellen Sie also ein neues C # -Skript mit dem Namen Spiel
und geben Sie einige Variablen, um drei Objekte aufzunehmen: a Ritter, ein Schurke, und ein Magier. Ändern Sie den Code dieses Skripts wie folgt:
mit UnityEngine; using System.Collections; [System.Serializable] öffentliche Klasse Spiel public static Spiel aktuell; public Charakter Ritter; public Charakterschurke; öffentlicher Charakterassistent; öffentliches Spiel () Ritter = neuer Charakter (); Schurke = neuer Charakter (); Assistent = neuer Charakter ();
Das [System.Serializable]
Zeile sagt Unity, dass dieses Skript sein kann serialisiert-Mit anderen Worten, dass wir alle Variablen in diesem Skript speichern können. Cool! Laut den offiziellen Dokumenten kann Unity die folgenden Typen serialisieren:
int
, Schnur
, schweben
, und bool
).Vector2
, Vector3
, Vector4
, Quaternion
, Matrix4x4
, Farbe
, Rect
, und Ebenenmaske
).UnityEngine.Object
(einschließlich GameObject
, Komponente
, MonoBehavior
, Textur2D
, und AnimationClip
).Die erste Variable, aktuell
, ist ein statischer Verweis auf a Spiel
Beispiel. Wenn wir ein Spiel erstellen oder laden, setzen wir diese statische Variable auf diese bestimmte Spielinstanz, damit wir von irgendwo im Projekt auf das "aktuelle Spiel" verweisen können. Durch die Verwendung statischer Variablen und Funktionen müssen wir keine gameObject
's GetComponent ()
Funktion. Praktisch!
Beachten Sie, dass es auf etwas verweist, das als a bezeichnet wird Charakter
? Wir haben das noch nicht, also erstellen wir ein neues Skript, um diese Klasse unterzubringen, und rufen es auf Charakter
:
mit UnityEngine; using System.Collections; [System.Serializable] public class Zeichen Name der öffentlichen Zeichenfolge; public Character () this.name = "";
Sie fragen sich vielleicht, warum wir eine ganz neue Klasse brauchten, wenn wir nur eine Stringvariable speichern. In der Tat könnten wir einfach ersetzen Charakter
in dem Spiel
zu verwendendes Skript Schnur
stattdessen. Aber ich möchte Ihnen zeigen, wie tief dieses Kaninchenloch gehen kann: Sie können Klassen speichern und laden, die andere Klassen referenzieren, und so weiter, solange Jede Klasse ist serialisierbar.
Nun, da unsere Klassen so eingerichtet sind, dass sie gespeichert und geladen werden können, kehren wir zu unseren zurück SaveLoad
Skript und fügen Sie die Fähigkeit hinzu, Spiele zu speichern.
Ein "Load Game" -Menü zeigt normalerweise eine Liste der gespeicherten Spiele, also erstellen wir ein Liste
vom Typ Spiel
und nenne es SavedGames
. Mache es ein statische Liste
, Es gibt also nur eine Liste der gespeicherten Spiele in unserem Projekt. Der Code sollte so aussehen:
mit UnityEngine; using System.Collections; using System.Collections.Generic; using System.Runtime.Serialization.Formatters.Binary; using System.IO; öffentliche statische Klasse SaveLoad öffentliche statische ListesavedGames = neue Liste ();
Als Nächstes erstellen wir eine neue statische Funktion zum Speichern eines Spiels:
public static void Save () savedGames.Add (Game.current); BinaryFormatter bf = new BinaryFormatter (); FileStream-Datei = File.Create (Application.persistentDataPath + "/savedGames.gd"); bf.Serialize (Datei, SaveLoad.savedGames); file.Close ();
Zeile 2 fügt unser aktuelles Spiel unserer Liste der gespeicherten Spiele hinzu. Diese Liste wird von uns serialisiert. Dazu müssen wir zuerst ein neues erstellen BinaryFormatter
, das wird die Serialisierungsarbeit erledigen. Dies ist, was Linie 3 tut.
In Zeile 4 erstellen wir eine Datenfluss
, Dies ist im Wesentlichen ein Weg zu einer neuen Datei, die wir auch Daten senden können, wie z. B. Fische, die stromabwärts in einem Fluss schwimmen. Wir gebrauchen File.Create ()
Um eine neue Datei am Ort zu erstellen, übergeben wir sie als Parameter. Praktischerweise verfügt Unity über einen integrierten Speicherort für unsere Spieldateien (die automatisch auf Grundlage der Plattform, auf der Ihr Spiel basiert, aktualisiert werden), auf die wir zugreifen können Application.persistentDataPath
.
Da wir jedoch eine neue Datei erstellen, können wir nicht einfach sagen, wo sich die Datei befindet. Wir müssen diesen Pfad auch mit dem Namen der eigentlichen Datei selbst abschließen. Diese Datei besteht aus zwei Teilen:
Wir werden verwenden SavedGames
für den Dateinamen, und wir verwenden einen benutzerdefinierten Datentyp gd
(für "Spieldaten") für den Dateityp. Unser Ergebnis ist eine Spieldatei namens SavedGames.gd
an dem von Application.persistentDataPath
. (In Zukunft könnten Sie andere Arten von Dingen in diesem Datentyp speichern, beispielsweise können Sie die Optionseinstellungen der Benutzer als speichern options.gd
.)
Hinweis: Sie können den Dateityp beliebig gestalten. Zum Beispiel verwendet die Elder Scrolls-Serie .esm
als Dateityp. Sie hätten es so leicht sagen können SavedGames.baconAndGravy
.
In Zeile 5 rufen wir die Serialisieren
Funktionalität des BinaryFormatter
um unsere zu retten SavedGames
Liste zu unserer neuen Datei. Danach haben wir in Zeile 6 die von uns erstellte Datei geschlossen.
Badda Bing, Badda-Boom. Unsere Spiele sind gerettet.
In dem sparen
Funktion haben wir unsere Liste der gespeicherten Spiele an einem bestimmten Ort serialisiert. Umgekehrt sollte der Code zum Laden unserer Spiele folgendermaßen aussehen:
public static void Load () if (File.Exists (Application.persistentDataPath + "/savedGames.gd")) BinaryFormatter bf = new BinaryFormatter (); FileStream-Datei = File.Open (Application.persistentDataPath + "/savedGames.gd", FileMode.Open); SaveLoad.savedGames = (Liste) bf.Deserialize (Datei); file.Close ();
In Zeile 2 prüfen wir, ob eine gespeicherte Spieldatei existiert. (Wenn dies nicht der Fall ist, gibt es offensichtlich nichts zu laden.) In Zeile 3 erstellen wir eine BinaryFormatter
auf die gleiche Weise wie im sparen
Funktion. In Zeile 4 erstellen wir eine Datenfluss
-Diesmal schwimmen unsere Fische jedoch stromaufwärts von der Akte. Also benutzen wir Datei.
Öffnen
, und zeigen auf wo unser SavedGames.gd
existiert mit dem gleichen Application.persistentDataPath
Schnur.
Linie 5 ist etwas dicht, also packen wir sie aus:
bf.Deserialize (Datei)
call findet die Datei an dem oben angegebenen Ort und deserialisiert sie. Liste
vom Typ Spiel. In Zeile 6 schließen wir diese Datei auf die gleiche Weise wie in der sparen
Funktion.
Hinweis: Der Datentyp, in den Sie die deserialisierten Daten umwandeln, kann sich je nach Bedarf ändern. Zum Beispiel, Player.lives = (int) bf.Deserialize (Datei);
.
Unsere SaveLoad
Das Skript ist jetzt abgeschlossen und sollte folgendermaßen aussehen:
mit UnityEngine; using System.Collections; using System.Collections.Generic; using System.Runtime.Serialization.Formatters.Binary; using System.IO; öffentliche statische Klasse SaveLoad öffentliche statische ListesavedGames = neue Liste (); // es ist statisch, also können wir es von überall aus aufrufen public static void Save () SaveLoad.savedGames.Add (Game.current); BinaryFormatter bf = new BinaryFormatter (); //Application.persistentDataPath ist eine Zeichenfolge. Wenn Sie möchten, können Sie dies in debug.log einfügen, wenn Sie wissen möchten, wo sich die Sicherungsspiele befinden. // Sie können es beliebig nennen. bf.Serialize (file, SaveLoad.savedGames); file.Close (); public static void Load () if (File.Exists (Application.persistentDataPath + "/savedGames.gd")) BinaryFormatter bf = new BinaryFormatter (); FileStream-Datei = File.Open (Application.persistentDataPath + "/savedGames.gd", FileMode.Open); SaveLoad.savedGames = (Liste ) bf.Deserialize (Datei); file.Close ();
Dies sind die Grundlagen zum Speichern und Laden in Unity. In der angehängten Projektdatei finden Sie einige andere Skripte, die zeigen, wie ich mit dem Aufrufen dieser Funktionen umgehe und wie ich die Daten mithilfe der Unity-GUI anzeigen kann.
Wenn Sie einen Vorsprung bei der Entwicklung Ihres Spiels benötigen, probieren Sie die auf Envato Market verfügbaren Unity3D-Vorlagen.