'Binary XML' untuk data game?

17

Saya sedang mengerjakan alat pengeditan level yang menyimpan datanya sebagai XML.

Ini ideal selama pengembangan, karena tidak sulit untuk membuat perubahan kecil pada format data, dan ini bekerja dengan baik dengan data seperti pohon.

The downside, meskipun, adalah bahwa file XML agak membengkak, sebagian besar karena duplikasi nama tag dan atribut. Juga karena data numerik mengambil lebih banyak ruang secara signifikan daripada menggunakan tipe data asli. Level kecil bisa dengan mudah berakhir sebagai 1 MB +. Saya ingin menurunkan ukuran ini secara signifikan, terutama jika sistem ini akan digunakan untuk permainan di iPhone atau perangkat lain dengan memori yang relatif terbatas.

Solusi optimal, untuk memori dan kinerja, akan mengkonversi XML ke format tingkat biner. Tetapi saya tidak ingin melakukan ini. Saya ingin menjaga formatnya tetap fleksibel. XML membuatnya sangat mudah untuk menambahkan atribut baru ke objek, dan memberi mereka nilai default jika versi lama dari data dimuat. Jadi saya ingin tetap dengan hierarki node, dengan atribut sebagai pasangan nama-nilai.

Tapi saya perlu menyimpan ini dalam format yang lebih ringkas - untuk menghapus duplikasi nama tag / atribut yang masif. Mungkin juga untuk memberikan atribut tipe asli, jadi, misalnya data titik-mengambang disimpan sebagai 4 byte per float, bukan sebagai string teks.

Google / Wikipedia mengungkapkan bahwa 'XML biner' bukan masalah baru - sudah dipecahkan beberapa kali. Adakah yang punya pengalaman di sini dengan sistem / standar yang ada? - apakah ada yang ideal untuk penggunaan game - dengan parser / loader library (C / C ++) gratis, ringan dan lintas platform?

Atau haruskah saya menemukan kembali roda ini sendiri?

Atau apakah saya lebih baik melupakan yang ideal, dan hanya mengompresi data .xml mentah saya (ini harus dikemas dengan baik dengan kompresi mirip zip), dan hanya mengambil memori / kinerja mencapai on-load?

bluescrn
sumber
1
XML dapat dikompres menggunakan gzip et al dengan sangat baik.
ThiefMaster

Jawaban:

18

Kami banyak menggunakan XML biner untuk Pengembalian Superman: Videogame . Kami berbicara ribuan file. Itu bekerja dengan baik, tetapi jujur ​​tampaknya tidak sepadan dengan usaha. Itu memakan sebagian kecil dari waktu pemuatan kami, dan "fleksibilitas" XML tidak meningkat. Setelah beberapa saat, file data kami memiliki terlalu banyak pengidentifikasi aneh, referensi eksternal yang perlu disinkronkan, dan persyaratan aneh lainnya agar benar-benar layak diedit oleh manusia lagi.

Juga, XML benar-benar format markup, dan bukan format data. Ini dioptimalkan untuk banyak teks dengan tag sesekali. Itu tidak bagus untuk data terstruktur penuh. Itu bukan panggilan saya, tetapi jika sudah dan saya tahu apa yang saya tahu sekarang, saya mungkin akan melakukan JSON atau YAML. Keduanya cukup singkat untuk tidak memerlukan pemadatan, dan dioptimalkan untuk merepresentasikan data , bukan teks .

banyak sekali
sumber
1
Ada versi biner dari JSON yang disebut BSON .
Philipp
12

Simpan dan edit level Anda sebagai XML normal, tetapi minta mesin game Anda dengan malas memanggangnya menjadi XML biner selama memuat, dan menyimpan XML biner kembali ke disk sehingga dapat memuatnya di lain waktu (jika XML mentah belum berubah) .

Sesuatu seperti ini:

data loadXml(xmlFile)
{
    if (xmlFile has changed OR binFile doesn't exist)
    {
        binFile = convertToBinary(xmlFile)
        save(binFile)
    }
    return loadBinaryXml(binFile)
}

Dengan begitu Anda mendapatkan yang terbaik dari kedua dunia. Pada rilis, Anda hanya perlu memastikan semua file biner ada di sana.

Peter Alexander
sumber
5

Google Protocol Buffer sepertinya cara untuk melakukannya, tetapi saya belum menggunakannya sendiri.
http://code.google.com/p/protobuf/

Anda mendefinisikan file .proto yang menjelaskan format file:

message Person {
  required int32 id = 1;
  required string name = 2;
  optional string email = 3;
}

Ini kemudian dikompilasi dengan alat baris perintah yang menghasilkan kelas C / C ++ untuk menulis dan mengurai file data biner dalam format data yang didefinisikan sebelumnya. Ada juga beberapa ekstensi untuk berbagai bahasa pemrograman.

Kelemahan dari ProtocolBuffer adalah bahwa mereka bukan format plaintext. Anda membutuhkan alat untuk membuat, membaca, dan mengeditnya. Tapi ini seharusnya tidak menjadi masalah jika Anda menggunakannya hanya untuk bertukar data antara editor game Anda dan game Anda. Saya tidak akan menggunakannya untuk mendefinisikan file konfigurasi;)

Mengompresi file xml mentah juga harus berfungsi. Jenis permainan apa yang Anda buat? Jika berbasis level maka Anda harus memuat semua sumber daya yang diperlukan hanya sekali ketika level dimuat.

pembaruan: Ada beberapa proyek untuk bahasa lain seperti C # untuk bekerja dengan ProtocolBuffers:
http://code.google.com/p/protobuf/wiki/ThirdPartyAddOns

Stephen
sumber
Bukankah serializer disesuaikan dengan masalah seperti itu? Saya kira tidak tetapi saya tidak melihat perbedaan yang jelas. Tetapi bagi saya jawaban ini sepertinya tepat. Tetapi juga tar / gzip file xml akan sangat mengurangi ukurannya (karena itu teks, tapi saya kira itu juga akan berfungsi untuk xml), jadi itu mungkin solusi "lebih mudah". Bagaimanapun XML adalah bahasa yang mudah, tetapi sangat mahal dalam hal parsing / menggunakan memori: ketika Anda menggunakan XML Anda harus membaca / menulis sesering mungkin.
jokoon
Ini merupakan opsi yang menarik, tetapi lebih mirip alternatif lengkap untuk menggunakan XML di mana saja dalam pipa. Sejujurnya, saya tidak akan terlalu antusias tentang kode yang dihasilkan, - dan kerumitan lain adalah saya menggunakan C # untuk sisi-sisi alat (saya senang alat terus bekerja dengan file .XML yang besar ). Konverter XML-> PB mungkin menjadi pilihan, meskipun saya pikir saya masih mencari sesuatu yang lebih 'XML biner tujuan umum', daripada cara untuk memanggang 'data tingkat biner' tertentu (bahkan jika itu akan menjadi sedikit lebih efisien)
bluescrn
"Saya menggunakan C # untuk sisi alat" ada beberapa proyek untuk c #. memperbarui jawaban saya.
Stephen
@bluescrn, saya tidak akan terlalu khawatir tentang kode yang dihasilkan. Google memberikan dukungan kelas 1 untuk C ++, Java, dan Python. Mereka menggunakannya secara internal; kode yang dihasilkan cukup kuat. Satu keuntungan besar dengan PB, adalah program alat Anda terhadap .protofile, yang hampir menghilangkan masalah miskomunikasi. Protos jauh lebih mudah dibaca / dipelihara daripada skema xml, jika Anda bahkan memiliki disiplin (dan waktu) untuk menggunakan skema xml.
deft_code
4

Bagaimana dengan format JSON?

http://www.json.org/xml.html

Sven
sumber
Itu terlihat sedikit lebih kompak daripada XML, tetapi masih memiliki masalah utama dari nama atribut yang digandakan. Jika file berisi daftar objek game dengan atribut 'XPosition', 'YPosition', dan 'Scale', string 'XPosition' / 'YPosition' / 'Scale' akan diduplikasi untuk setiap objek game tunggal. Ini adalah hal utama yang ingin saya 'kompres' saat ini
bluescrn
1
@ bluescrn: Tidak, tidak ada masalah. Objek adalah satu struktur; Anda juga bisa menggunakan array [yang, hanya, lihat, seperti, ini]. Itu berarti Anda bisa berakhir dengan sesuatu seperti ini untuk menyimpan nama dan properti mobil: "cars":{"ford":[8C,FA,BC,2A,384FFFFF],"holden":[00,00,04,FF,04FF54A9]}Anda bahkan dapat menghilangkan pengidentifikasi "mobil" dan langsung masuk ke array jika Anda tahu di mana lapangan mobil akan berada. Anda bahkan dapat menghilangkan "ford" dan "holden" nama jika Anda tidak perlu menyimpan data itu, meninggalkan Anda dengan: [...,[[8C,FA,BC,2A,384FFFFF],[00,00,04,FF,04FF54A9]]]. Apakah ini menjadi lebih ringkas?
doppelgreener
1
@Axidos: Jika Anda ingin membuat markup yang tidak dapat dibaca dan tidak terstruktur, Anda mungkin juga membuatnya menjadi biner. Selain itu, ini adalah penghematan palsu, kecuali jika Anda mem-parsing data yang tidak terkompresi selama runtime (dalam hal ini, Anda mungkin masih mengacaukannya), atau entah bagaimana dibatasi untuk beberapa ratus byte memori string selama penguraian (kecuali Anda berada di microwave, Anda tidak).
@ Jo: bluescrn tampaknya mencari format yang dapat dibaca yang tidak memiliki nama duplikat. Saya menggambarkan kemampuan JSON untuk menawarkan hal itu. Saya setuju sepenuhnya bahwa pada titik tertentu Anda mungkin juga bertanya-tanya mengapa Anda bahkan repot dengan markup seperti ini.
doppelgreener
4

Gunakan JSON.

(Membangun tanggapan Munificent, dan sebagian besar sebagai tanggapan atas keprihatinan Anda yang diungkapkan di tempat lain)

Anda telah menyebutkan kekhawatiran bahwa JSON memiliki masalah membuang elemen penamaan ruang, seperti XML. Tidak.

JSON dibangun di atas dua struktur: pasangan nama / nilai ( objek ) dan daftar nilai yang terurut ( array ). XML dibangun hanya pada pasangan nama / nilai.

Jika Anda berpikir JSON mengandalkan objek yang telah Anda baca, JSON yang dibangun untuk bersifat deskriptif dan dapat dibaca manusia, seperti ini (menggunakan pasangan digit oktal untuk mewakili byte tunggal):

{
    "some": ...,
    "data": ...,
    "fields": ...,
    "cars": [
        {"name":"greg","cost":8C,"speed":FA,"age":04,"driverID":384FFFFF},
        {"name":"ole rustbucket","cost":00,"speed":00,"age":2A,"driverID":04FF54A9}
    ]
}

Namun Anda juga memiliki pilihan untuk menulisnya seperti ini, selama Anda tahu di mana semuanya akan berada (dan dapat mencari indeks 4, daripada objek "mobil", untuk mendapatkan daftar mobil Anda):

{
    [
        ...,
        ..., 
        ...,
        [["greg",8C,FA,04,384FFFFF],["ole rustbucket",00,00,2A,04FF54A9]],
        ...,
    ]
}

Apakah itu bisa lebih ringkas daripada hanya memiliki [, ], ,dan nilai-nilai Anda?

Ya, itu terjadi jika Anda bersedia untuk semakin dekat dan lebih dekat ke aliran biner murni.

"cars":{"names":["greg","ole rustbucket"],"stream":8CFA04384FFFFF00002A04FF54A9}
or
[["greg","ole rustbucket"],8CFA04384FFFFF00002A04FF54A9]

Hanya saja, jangan menembak diri sendiri dengan mengoptimalkan terlalu banyak.

doppelgreener
sumber
2

Saya tahu Anda telah menerima jawaban, tetapi Google "Fast Infoset" (binary XML) dan vtd-xml.

Meskipun yang terakhir (VTD) mungkin tidak menyelesaikan aspek kompresi penggunaan XML Anda, itu mungkin mempercepat akses node di file besar, jauh (itu menggunakan 'kamus' offset biner untuk melompat ke node, dan tidak membuat objek untuk setiap node , alih-alih bekerja pada string XML asli). Oleh karena itu, pencarian XML-nya [dikatakan] lebih cepat dan tidak memerlukan banyak memori dalam proses untuk mengakses / memanipulasi dokumen XML.

Kedua hal di atas memiliki binding dalam bahasa populer (yang termasuk C #).

Bersulang

Kaya

Kaya Besar
sumber
1

Anda bisa mencoba Karvonite . Seharusnya lincah. Ini adalah kerangka kerja tetap yang akan beradaptasi dengan perubahan data Anda dengan cukup baik (yang lebih baik dibandingkan dengan menangani biner diri Anda). Saya tidak benar-benar yakin bagaimana data terstruktur, tetapi file-file ini jauh lebih kecil daripada file kembung xml. (Saya berasumsi ini menyimpan data dalam format biner alih-alih teks seperti xml)

Satu-satunya hal yang bisa saya pikirkan dengan ini adalah bahwa jika data Anda rusak atau seberapa kacau dengan cara yang tidak disukai Karvonite, jenis Anda pada belas kasihan pembuatnya kecuali jika Anda mengetahui bagaimana struktur dari data bekerja.

Cara Anda menentukan cara menyimpan / memuat data adalah Anda cukup membuka editor kegigihan mereka, mengimpor unit Anda dengan semua objek data dan mencentang beberapa kotak centang untuk menunjukkan objek apa yang ingin didukung dan bidang / properti apa yang akan disimpan.

Mungkin patut dicoba. Karena Anda menggunakan C #, ini cocok dengan bahasa Anda karena berfungsi dengan XNA (Windows, Xbox360, dan Windows Phone 7 yang saya pikir Anda tertarik sejak Anda menyebutkan iPhone?).

Sunting: Hanya perhatikan bahwa Anda hanya menggunakan C # untuk alat-alat tersebut. Ini mungkin tidak cocok dengan alur kerja Anda. Untuk beberapa alasan saya memiliki XNA di kepala saya.

Michael Coleman
sumber