Come posso gestire le modifiche di versione durante il salvataggio delle risorse?


9

Ho lavorato su un gioco di ruolo per un po 'e utilizzo due diverse tecniche di serializzazione.

  • Nemici, armi, oggetti vengono salvati come XML.
  • Le mappe e gli eventi vengono salvati come "binari controllati" (ogni classe ottiene un metodo di salvataggio / caricamento e decide cosa salvare / caricare).

Ma ho iniziato a mettere in discussione la mia scelta per mappe ed eventi. Le mie preoccupazioni:

  • Ho creato un editor di mappe ma mi manca ancora la possibilità di cambiare piccole cose semplicemente aprendo il file.
  • I cambiamenti fanno casino così tanto. Dì che voglio aggiungere una variabile a una classe, se non carico / salvo di nuovo ogni mappa si rompe in seguito.

La prima preoccupazione è difficile da aggirare senza cambiare la mia tecnica. Ho pensato di passare a JSON, ma è un sacco di lavoro. Penso anche che sia piuttosto brutto con gli attributi [DataContract] e [DataMember] ovunque.

Questo mi lascia con la mia seconda preoccupazione e mi chiedo come posso farcela? Crei un piccolo programma che attraversa tutte le mappe e le salva nuovamente con la nuova variabile? Perché ora inizio a ottenere un paio di mappe e lo faccio ancora manualmente. Mi fa pensare due volte ogni volta che voglio fare alcune modifiche in quanto crea molto lavoro extra.

Risposte:


5

Esistono molti modi per gestire il problema delle versioni; puoi farlo avendo una funzione di caricamento per versione, puoi provare ad automatizzare il processo descrivendo (attraverso gli attributi di solito) la trasformazione della struttura degli asset nel tempo, puoi fare controlli specifici della versione all'interno delle funzioni di caricamento / salvataggio, eccetera .

Mi piace l'approccio "descrivi i cambiamenti", ma trovo che provare a farlo tramite gli attributi diventa scomodo e veloce . Userei invece le funzioni; implementare una funzione che trasforma i dati in versione Nin dati in versione N + 1per tutta la versione appropriata. Al caricamento, controlla la versione con l'ultima e, in caso contrario, esegui i dati attraverso tutte le funzioni di versioning appropriate. Salva sempre l'ultima versione.

Funziona meglio se si esegue la trasformazione quando i dati sono ancora in un formato valore-chiave runtime. Ciò significa che probabilmente vorrai implementare una rappresentazione per i tuoi dati che è un approccio "runtime bag of properties", perché non puoi utilizzare il modulo chiave-valore sottostante di JSON o XML se hai il tuo formato binario. Se non lo fai, potresti anche aver bisogno di mantenere vecchie definizioni di classe, il che diventa brutto. Essere in grado di avere le tue risorse in questo cattivo formato della proprietà è anche estremamente utile per lo sviluppo dell'editor di giochi.

Durante lo sviluppo man mano che esegui l'iterazione dei tuoi dati, salirà naturalmente all'ultima versione e alla fine potrai eliminare le vecchie funzioni di controllo delle versioni. Questo è più o meno lo stesso approccio di alto livello utilizzato per la versione degli asset grafici (come le mappe) in Guild Wars 2.


Ora, tutto ciò detto, penso che sia utile supportare sia la serializzazione di testo che binaria per le risorse. Durante lo sviluppo, conserva tutti i tuoi dati in un formato leggibile dall'uomo basato su XML o JSON. Ciò può aumentare molto la tua capacità di iterazione perché non è necessario creare strumenti così complessi per la modifica dei dati. Puoi tornare a essere in grado di apportare semplici modifiche rapide a mano.

In secondo luogo, supponendo che si desideri ancora un formato binario per la spedizione del gioco (che può migliorare le dimensioni del file o i tempi di I / O del file, quindi è un desiderio valido), progettare le API di serializzazione e deserializzazione per gestire il versioning. Il controllo delle versioni è ancora utile in un contesto di spedizione, perché come alcuni punti potresti voler spedire aggiornamenti o correzioni di bug. Ci sono alcuni documenti che descrivono le capacità di versioning della serializzazione .NET e della serializzazione di Boost che potresti trovare interessanti. Se si sta andando a supportare sia il testo e formati binari, assicurarsi di testare loro di tanto in tanto (o test di compilazione automatica di farlo, ancora meglio).


Grazie per il commento, mi ha dato alcune idee su come continuare.
user1776562

1

Utilizzare un linguaggio di markup con coppie attributo-valore come XML o JSON.

Il parser può semplicemente ignorare tutti gli attributi che non comprende o utilizzare i valori predefiniti per quelli che non trova, il che rende la compatibilità avanti e indietro piuttosto semplice. Inoltre, il formato è leggibile dall'uomo in modo da poterlo modificare facilmente con un editor di testo.

Quando usi un linguaggio consolidato come XML o JSON noterai anche che molti linguaggi di scripting lo supportano, quindi quando avrai ancora bisogno di scrivere uno script per modificare un gran numero di file, troverai molto più facile farlo.

Lo svantaggio della maggior parte di queste lingue è che sono piuttosto prolissi. Ciò significa che i file risultanti sono molto più grandi di quanto dovrebbero essere con un formato binario ottimizzato. Al giorno d'oggi, la dimensione del file non importa troppo nella maggior parte delle situazioni. Ma in quelli in cui è importante, la dimensione del file può spesso essere significativamente ridotta comprimendo il file con un algoritmo di magazzino come zip.

I linguaggi di markup spesso non consentono l'accesso casuale a meno che l'intero documento non venga letto dal disco rigido e analizzato. Ma in pratica questo non ha molta importanza, perché i dischi rigidi sono più veloci con letture sequenziali. La ricerca casuale più volte in diverse parti dello stesso file può spesso essere molto più lenta della semplice lettura del file in una sola volta, anche quando ciò significa che leggi più dati del necessario.


1

puoi usare protobuf. https://code.google.com/p/protobuf/ Ti offre i vantaggi di json / xml, che puoi facilmente estendere pur essendo compatibile con le versioni precedenti, oltre al vantaggio di essere binario. Il flusso di lavoro consiste nel creare una descrizione del formato dati nel linguaggio protobuf e quindi generare il codice sorgente per la serializzazione e la deserializzazione. La fonte può essere generata per diverse lingue. Inoltre, è un grande vantaggio avere una chiara specifica dei dati serializzati, a differenza di json in cui la specifica viene fatta implicitamente nella lettura / scrittura.


Sembra bello ma io uso c #, questo sembra essere per c ++, python e java.
user1776562

Esiste una versione C #. Non l'ho testato personalmente, ma ce n'è uno.
Arne,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.