Wie kann ich beim Speichern von Assets mit Versionsänderungen umgehen?

9

Ich arbeite jetzt seit einer Weile an einem Rollenspiel und verwende zwei verschiedene Serialisierungstechniken.

  • Feinde, Waffen und Gegenstände werden genauso gespeichert wie XML.
  • Karten und Ereignisse werden als "kontrollierte Binärdatei" gespeichert (jede Klasse erhält eine Methode zum Speichern / Laden und entscheidet, was sie speichern / laden möchte).

Aber ich habe angefangen, meine Wahl für Karten und Ereignisse in Frage zu stellen. Meine Bedenken:

  • Ich habe einen Karteneditor erstellt, aber ich vermisse es immer noch, kleine Dinge durch einfaches Öffnen der Datei ändern zu können.
  • Änderungen bringen so viel durcheinander. Angenommen, ich möchte einer Klasse eine Variable hinzufügen. Wenn ich nicht jede Karte erneut lade / speichere, wird sie später unterbrochen.

Die erste Sorge ist schwer zu umgehen, ohne meine Technik zu ändern. Ich habe darüber nachgedacht, zu JSON zu wechseln, aber es ist viel Arbeit. Ich finde es auch ziemlich hässlich mit den Attributen [DataContract] und [DataMember] überall.

Das lässt mich mit meiner zweiten Sorge zurück und ich frage mich, wie ich damit umgehen kann? Erstellen Sie ein kleines Programm, das alle Karten durchläuft und sie mit der neuen Variablen erneut speichert? Weil ich jetzt anfange, ein paar Karten zu bekommen und es immer noch manuell mache. Ich denke jedes Mal zweimal darüber nach, wenn ich Änderungen vornehmen möchte, da dies viel zusätzliche Arbeit verursacht.

user1776562
quelle

Antworten:

5

Es gibt viele Möglichkeiten, das Versionsproblem zu lösen. Sie können dies tun, indem Sie eine Ladefunktion pro Version haben. Sie können versuchen, den Prozess zu automatisieren, indem Sie (normalerweise über Attribute) die Transformation der Asset-Struktur im Laufe der Zeit beschreiben. Sie können versionenspezifische Überprüfungen innerhalb der Lade- / Speicherfunktionen usw. durchführen .

Ich mag den Ansatz "Beschreibe die Änderungen", finde aber, dass der Versuch, dies über Attribute zu tun, schnell unangenehm wird . Ich würde stattdessen Funktionen verwenden; Implementieren Sie eine Funktion, die Daten in Version Nin Daten in Version N + 1für alle Ihre entsprechenden Versionen umwandelt . Überprüfen Sie beim Laden die Version mit der neuesten Version. Wenn dies nicht der Fall ist, führen Sie die Daten über alle entsprechenden Versionsfunktionen aus. Speichern Sie immer die neueste Version.

Dies funktioniert am besten, wenn Sie die Transformation durchführen, während sich die Daten noch in einer Laufzeit-Schlüsselwertform befinden. Dies bedeutet, dass Sie wahrscheinlich eine Darstellung für Ihre Daten implementieren möchten, bei der es sich um einen "Runtime Bag of Properties" -Ansatz handelt, da Sie die zugrunde liegende Schlüsselwertform von JSON oder XML nicht verwenden können, wenn Sie über ein eigenes Binärformat verfügen. Wenn Sie dies nicht tun, müssen Sie möglicherweise auch alte Klassendefinitionen beibehalten, was hässlich wird. Die Möglichkeit, Ihre Assets in diesem schlechten Format zu haben, ist auch für die Entwicklung des Spieleditors äußerst nützlich.

Während der Entwicklung, während Sie Ihre Daten iterieren, sprudelt es natürlich auf die neueste Version und Sie können schließlich die alten Versionsfunktionen löschen. Dies ist mehr oder weniger der gleiche Ansatz auf hoher Ebene, mit dem wir Kunstobjekte (wie die Karten) in Guild Wars 2 versioniert haben.


Alles in allem halte ich es für nützlich, sowohl die Text- als auch die binäre Serialisierung für Assets zu unterstützen. Bewahren Sie während der Entwicklung alle Ihre Daten in einem für Menschen lesbaren Format auf, das auf XML oder JSON basiert. Dies kann Ihre Iterationsfähigkeit erheblich verbessern, da Sie keine so komplexen Tools zum Bearbeiten der Daten erstellen müssen. Sie können wieder einfache, schnelle Änderungen von Hand vornehmen.

Zweitens: Nehmen Sie an, Sie möchten sogar noch ein Binärformat für den Versand des Spiels (das die Dateigröße oder die Datei-E / A-Zeiten verbessern kann, was ein berechtigter Wunsch ist), und entwerfen Sie Ihre Serialisierungs- und Deserialisierungs-APIs für die Versionierung. Die Versionsverwaltung ist im Versandkontext immer noch nützlich, da Sie möglicherweise irgendwann Updates oder Fehlerbehebungen versenden möchten. Es gibt einige Dokumente, die die Versionsfunktionen der .NET-Serialisierung und der Boost-Serialisierung beschreiben , die Sie vielleicht interessant finden. Wenn Sie sind sowohl Text als auch Binärformaten unterstützen, stellen Sie sicher , dass Sie sie testen , gelegentlich (oder Build automatisierte Tests zu tun, noch besser).


quelle
Vielen Dank für den Kommentar, gab mir einige Ideen, wie ich fortfahren soll.
user1776562
1

Verwenden Sie eine Auszeichnungssprache mit Attribut-Wert-Paaren wie XML oder JSON.

Der Parser kann einfach alle Attribute ignorieren, die er nicht versteht, oder Standardeinstellungen für nicht verwendete Attribute verwenden, was die Abwärts- und Vorwärtskompatibilität recht einfach macht. Außerdem ist das Format für Menschen lesbar, sodass Sie es problemlos mit einem Texteditor bearbeiten können.

Wenn Sie eine etablierte Sprache wie XML oder JSON verwenden, werden Sie auch feststellen, dass viele Skriptsprachen diese unterstützen. Wenn Sie also noch ein Skript schreiben müssen, um eine große Anzahl von Dateien zu bearbeiten, ist dies viel einfacher.

Der Nachteil der meisten dieser Sprachen ist, dass sie ziemlich ausführlich sind. Das bedeutet, dass die resultierenden Dateien viel größer sind, als sie mit einem optimierten Binärformat benötigt würden. Heutzutage spielt die Dateigröße in den meisten Situationen keine große Rolle. In Fällen, in denen es darauf ankommt, kann die Dateigröße häufig erheblich reduziert werden, indem die Datei mit einem Standardalgorithmus wie zip komprimiert wird.

Markup-Sprachen erlauben häufig keinen wahlfreien Zugriff, es sei denn, das gesamte Dokument wird von der Festplatte gelesen und analysiert. In der Praxis spielt dies jedoch keine große Rolle, da Festplatten mit sequentiellen Lesevorgängen am schnellsten sind. Das zufällige mehrfache Suchen nach verschiedenen Teilen derselben Datei kann oft viel langsamer sein, als nur die Datei auf einmal zu lesen, selbst wenn dies bedeutet, dass Sie mehr Daten lesen, als Sie benötigen.

Philipp
quelle
1

Sie können Protobuf verwenden. https://code.google.com/p/protobuf/ Es bietet Ihnen die Vorteile von json / xml, dass Sie es einfach erweitern können, während Sie abwärtskompatibel sind, sowie den Vorteil, binär zu sein. Der Workflow besteht darin, dass Sie eine Beschreibung des Datenformats in der Sprache protobuf erstellen und dann den Quellcode für die Serialisierung und Deserialisierung generieren. Die Quelle kann für mehrere Sprachen generiert werden. Es ist auch ein großer Vorteil, dass Sie eine klare Spezifikation Ihrer serialisierten Daten haben, im Gegensatz zu json, wo die Spezifikation implizit beim Lesen / Schreiben erfolgt.

Arne
quelle
Sieht cool aus, aber ich benutze c #, dies scheint für c ++, Python und Java zu sein.
user1776562
Es gibt eine C # -Version. Ich habe es nicht persönlich getestet, aber es gibt eine.
Arne