Wie speichere ich den Spielstatus?

27

Wie gehen die Spielprogrammierer vor, um den Spielstatus zu speichern und fortzusetzen? wie Dateien / Zuordnungen. Ich möchte es für das Tower Defense-Spiel speichern und verwende die unity3D-Game-Engine.

Syed
quelle

Antworten:

16

Ich denke im Allgemeinen nicht an einen Speicherauszug, sondern erstelle eine Liste der Werte, die zwischen Sitzungen gespeichert werden müssen, und speichere diese Werte in einer externen Datei.

Dies hängt natürlich von den Bedürfnissen Ihres Spiels ab, aber normalerweise speichere ich einfach den aktuellen Status (dh wo sich alle Feinde befinden, wie ihre Gesundheit ist usw.) und dann höherstufige Dinge wie die Levels des Spielers ist bereits abgeschlossen.

jhocking
quelle
3
+1 So mache ich es. Ich schreibe was ich brauche in eine Binärdatei. Und wenn ich etwas Neues hinzufügen muss, füge ich es am Ende hinzu, damit alte Sicherungsdateien nicht beschädigt werden.
chaosTechnician
Das ist ein guter Tipp, um alte Sicherungsdateien nicht zu beschädigen, obwohl das Hinzufügen von Daten am Ende für das Speichern von Daten unerheblich ist. Ich mache das, indem ich ein Dictionary serialisiere / deserialisiere, und die Reihenfolge ist in dieser Datenstruktur irrelevant.
jhocking
(Im Grunde genommen der Code in Jonas 'Antwort, wobei mein Objekt ein Wörterbuch ist)
jhocking
10

Diese Antwort ist Unity3d-spezifisch .
In Unity sind die meisten Klassen serialisierbar. Dies bedeutet, dass Sie vollständige Unity-Objekte auf die Festplatte streamen können. Mit dem folgenden UnityScript-Code können Sie ein Objekt serialisieren, auf der Festplatte speichern und erneut laden (nach dem Laden müssen Sie das Objekt umwandeln):

import System;
import System.IO;
import System.IO.Stream;
import System.Runtime.Serialization;
import System.Runtime.Serialization.Formatters.Binary;

class SaveLoad {
        public static function SaveFile(filename:String, obj:Object):void {
                try {
                        Debug.Log("Writing Stream to Disk.", SaveLoad);
                        var fileStream:Stream = File.Open(filename, FileMode.Create);
                        var formatter:BinaryFormatter = new BinaryFormatter();
                        formatter.Serialize(fileStream, obj);
                        fileStream.Close();
                } catch(e:Exception) {
                        Debug.LogWarning("Save.SaveFile(): Failed to serialize object to a file " + filename + " (Reason: " + e.ToString() + ")");
                }
        }

        public static function LoadFile(filename:String):Object {
                try {
                        Debug.Log("Reading Stream from Disk.", SaveLoad);
                        var fileStream:Stream = File.Open(filename, FileMode.Open, FileAccess.Read);
                        var formatter:BinaryFormatter = new BinaryFormatter();
                        var obj:Object= formatter.Deserialize(fileStream);
                        fileStream.Close();
                        return obj;
                } catch(e:Exception) {
                        Debug.LogWarning("SaveLoad.LoadFile(): Failed to deserialize a file " + filename + " (Reason: " + e.ToString() + ")");
                        return null;
                }       
        }
}
jonas
quelle
2
Neben der Verwendung von C # möchten Sie auch PlayerPrefs verwenden. Sie sind plattformübergreifend und können nicht auf Web / iOS / Android ausgeführt werden. unity3d.com/support/documentation/ScriptReference/… (Nettes Beispiel!)
TJHeuvel
PlayerPrefs sind viel weniger flexibel, sie sind in der Tat plattformübergreifend und sie eignen sich perfekt zum Speichern einzelner oder nicht verwandter Werte. Aber unter Windows PlayerPrefs sind in der Registrierung Klartext gespeichert.
Jonas
7
Wenn Sie bereits serialisieren, können Sie es in einen String serialisieren und in PlayerPrefs speichern. Sicher ist es weniger flexibel, aber es ist so ziemlich die einzige Lösung für ein plattformübergreifendes Spiel.
TJHeuvel
2
PlayerPrefs eignet sich hervorragend zum Speichern kleiner Datenmengen wie Einstellungen. Für vollständige Spielstände
jhocking 27.12.14
2
@TJHeuvel: "Sie können IO nicht auf Web / iOS / Android ausführen" Sie können IO auf jeden Fall auf Mobilgeräten
ausführen
2

Für einen TD würde ich wohl ausschließlich zwischen den Wellen sparen. Auf diese Weise müssen Sie nur an die Türme denken. Setzen Sie einige automatische Speicherpunkte in die Ebenen, nicht mehr als 10 Minuten dazwischen, aber weniger ist wahrscheinlich vorzuziehen.

Wenn Ihre Levels kurz genug sind, können Sie natürlich nur den Kampagnenstatus speichern.

aaaaaaaaaaa
quelle
1

Wenn ich mich auf den aktuellen Stand des Spiels beziehe, beziehe ich mich auf den Speicherauszug zum Zeitpunkt des Speicherns. Sie müssen in der Lage sein, dies anhand der Daten, die Sie auf Ihrer Festplatte speichern möchten, wiederherzustellen.

Am einfachsten ist es, alle Klassen mit Daten, die persistent sein müssen, zu serialisieren und auf die Festplatte zu sichern. Dabei wird im Wesentlichen ein Speicherauszug ausgeführt. Das Problem dabei ist, dass das Ändern Ihrer Klassen die Anzahl / Typen der serialisierten Werte ändert und alte Speicherungen aufbricht. Auch weil Sie alles speichern, erhöht sich die Ladezeit. Es ist effizienter, einzelne Felder zu markieren, die tatsächlich benötigt werden, um den aktuellen "Speicher-Snapshot" mit dem von Ihrem Serializer / Ihrer IDE verwendeten Attributsystem wiederherzustellen. Erstellen Sie dann den "Speicher-Snapshot" aus diesen gespeicherten Daten neu.

Außerdem habe ich Unity noch nie benutzt, sodass möglicherweise etwas eingebaut ist. Dies ist jedoch der typische Ansatz.

ClassicThunder
quelle
Meinst du, ich muss meine Zustände in einer Datei speichern?
Syed
1
@Syed Ja, am Ende des Tages muss es in eine Datei geschrieben werden, da der App-Status nicht im Speicher gespeichert wird. Mit Unity können Sie speziell die PlayerPrefs-Klasse (die, wie ich glaube, Dinge in der Registrierung unter Windows speichert) verwenden, wenn Sie das Lesen / Schreiben der gesamten Datei vermeiden möchten.
Tetrad