Oyun verileri için 'İkili XML' mi?


17

Verilerini XML olarak kaydeden bir seviye düzenleme aracı üzerinde çalışıyorum.

Bu, veri biçiminde küçük değişiklikler yapmak acısız olduğu ve ağaç benzeri verilerle güzel çalıştığı için geliştirme sırasında idealdir.

Olumsuz tarafı, XML dosyalarının çoğunlukla etiket ve özellik adlarının çoğaltılması nedeniyle oldukça şişkin olmasıdır. Ayrıca sayısal verilerin yerel veri türlerini kullanmaktan çok daha fazla yer kaplaması nedeniyle. Küçük bir seviye kolayca 1Mb + olarak sonuçlanabilir. Özellikle sistem iPhone'da veya nispeten sınırlı belleği olan diğer cihazlarda bir oyun için kullanılacaksa, bu boyutları önemli ölçüde azaltmak istiyorum.

Bellek ve performans için en uygun çözüm, XML'i ikili düzey biçimine dönüştürmek olacaktır. Ama bunu yapmak istemiyorum. Biçimi oldukça esnek tutmak istiyorum. XML, nesnelere yeni özellikler eklemeyi ve verilerin eski bir sürümü yüklüyse onlara varsayılan bir değer vermeyi çok kolaylaştırır. Bu nedenle, ad-değer çiftleri olarak özniteliklerle düğüm hiyerarşisine bağlı kalmak istiyorum.

Ancak bunu daha kompakt bir formatta saklamam gerekiyor - etiket / özellik adlarının büyük kopyalarını kaldırmak için. Özniteliklere yerel türler de vermek için, örneğin, kayan nokta verileri bir metin dizesi olarak değil, kayan nokta başına 4 bayt olarak depolanır.

Google / Wikipedia, 'ikili XML'in neredeyse yeni bir sorun olduğunu ortaya koyuyor - zaten birkaç kez çözüldü. Buradaki herhangi biri mevcut sistem / standartlardan herhangi biri ile deneyime sahip mi? - Ücretsiz, hafif ve platformlar arası ayrıştırıcı / yükleyici kitaplığı (C / C ++) ile oyun kullanımı için herhangi bir ideal var mı?

Yoksa bu tekerleği kendim mi yeniden keşfetmeliyim?

Ya da ideali unutmaktan ve sadece ham .xml verilerimi sıkıştırmaktan (zip benzeri sıkıştırma ile iyi bir şekilde paketlenmelidir) ve sadece bellek / performans yükü üzerine yüklüyorum?


1
XML, gzip ve arkadaşları kullanılarak çok iyi sıkıştırılabilir .
ThiefMaster

Yanıtlar:


18

Superman Returns: The Videogame için ikili XML'yi yoğun olarak kullandık . Binlerce ve binlerce dosyadan bahsediyoruz. Tamam çalıştı, ama dürüst çabaya değer görünmüyordu. Yükleme süremizin dikkate değer bir kısmını yedik ve XML'in "esnekliği" artmadı. Bir süre sonra, veri dosyalarımızda çok fazla garip tanımlayıcı, senkronizasyonda tutulması gereken dış referanslar ve artık gerçekten insanca düzenlenebilmeleri için diğer garip gereksinimler vardı.

Ayrıca, XML gerçekten bir biçimlendirme biçimidir, bir veri biçimidir. Ara sıra etiketler içeren çok sayıda metin için optimize edilmiştir. Tamamen yapılandırılmış veriler için mükemmel değildir. Bu benim çağrım değildi, ama olsaydı ve şimdi ne bildiğimi biliyor olsaydım, muhtemelen JSON ya da YAML olurdu. Her ikisi de sıkıştırma gerektirmeyecek kadar kısadır ve metin değil verileri temsil edecek şekilde optimize edilmiştir .


1
JSON adlı ikili bir sürüm var JSON'un BSON .
Philipp

12

Seviyelerinizi normal XML olarak saklayın ve düzenleyin, ancak oyun motorunuzun yükleme sırasında ikili XML'ye tembel olarak pişirmesini sağlayın ve ikili XML'yi bir dahaki sefere yükleyebilmesi için diske geri kaydedin (ham XML değişmediyse) .

Bunun gibi bir şey:

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

Bu şekilde her iki dünyanın da en iyisini elde edersiniz. Serbest bırakıldığında, tüm ikili dosyaların orada olduğundan emin olmanız gerekir.


5

Google Protokolü Arabellekleri bir yol gibi görünüyor, ancak ben bunları kendim kullanmadım.
http://code.google.com/p/protobuf/

Dosya biçimini tanımlayan bir .proto dosyası tanımlarsınız:

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

Bu daha sonra, önceden tanımlanmış veri biçiminde ikili veri dosyalarını yazmak ve ayrıştırmak için C / C ++ sınıfları üreten bir komut satırı aracıyla derlenir. Farklı programlama dilleri için de birkaç eklenti vardır.

ProtocolBuffer'ın dezavantajı, düz metin biçimi olmamasıdır. Bunları oluşturmak, okumak ve düzenlemek için bir araca ihtiyacınız olacaktır. Ancak, bunları yalnızca oyun düzenleyiciniz ve oyununuz arasında veri alışverişi için kullanıyorsanız sorun olmamalıdır. Ben yapılandırma dosyalarını tanımlamak için kullanmak olmaz;)

Ham xml dosyalarının sıkıştırılması da çalışmalıdır. Ne tür bir oyun yapıyorsunuz? Seviye tabanlıysa, seviye yüklendiğinde tüm gerekli kaynakları yalnızca bir kez yüklemelisiniz.

güncelleme: C # gibi diğer dillerin ProtocolBuffers ile çalışması için birkaç proje var:
http://code.google.com/p/protobuf/wiki/ThirdPartyAddOns


Bir serileştirici bu tür bir probleme uyarlanmamış mı? Sanmıyorum ama net bir fark görmüyorum. Ama bana göre bu cevap uygun görünüyor. Ama aynı zamanda tar / gzip xml dosyaları büyük ölçüde boyutunu azaltacaktır (metin olduğu için, ama sanırım xml için de çalışacak), bu yüzden "daha kolay" bir çözüm olabilir. Her neyse, XML kolay bir dildir, ancak kullanarak ayrıştırma / bellek açısından çok pahalıdır: XML kullandığınızda mümkün olduğunca az okuma / yazma yapmalısınız.
jokoon

İlginç bir seçenektir, ancak XML'i boru hattının herhangi bir yerinde kullanmaya tam bir alternatif gibi görünür. Dürüst olmak gerekirse, ben oluşturulan kod hakkında çok hevesli değil woudln - ve başka bir komplikasyon şeylerin araçlar tarafı için C # kullanıyorum (araçların büyük .XML dosyalarıyla çalışmaya devam etmek için mutluyum ). Bir XML-> PB dönüştürücü bir seçenek olabilir, ancak yine de belirli 'ikili seviye verilerini' pişirmenin yollarından ziyade daha 'genel amaçlı ikili XML' olan bir şey arıyorum (bu biraz daha fazla olsa bile) verimli)
bluescrn

"Ben şeyler tarafında C # kullanıyorum" c # için birkaç proje vardır. cevabımı güncelledi.
Stephen

@bluescrn, oluşturulan kod hakkında çok endişelenmezdim. Google, C ++, Java ve Python'a 1. sınıf destek verir. Onu dahili olarak yaygın olarak kullanırlar; oluşturulan kod oldukça sağlamdır. PB'nin en büyük avantajlarından biri .proto, yanlış iletişim sorunlarını neredeyse ortadan kaldıran bir dosyaya karşı araç programınızdır . Protoları okumak / korumak xml şemalarını kullanmak için disipline (ve zamana) sahipseniz bir xml şemasına göre çok daha kolaydır.
usta_code 26:12

4

JSON formatı ne olacak?

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


XML'den biraz daha kompakt görünüyor, ancak yine de çoğaltılan öznitelik adları ana sorunu var. Dosya 'XPosition', 'YPosition' ve 'Scale' özniteliklerine sahip bir oyun nesneleri listesi içeriyorsa, 'XPosition' / 'YPosition' / 'Scale' dizeleri her oyun nesnesi için çoğaltılır. Şu anda 'sıkıştırmayı' hedeflediğim ana şey bu
bluescrn

1
@bluescrn: Hayır, böyle bir sorunu yok. Nesneler bir yapıdır; dizileri de kullanabilirsiniz [ki bu sadece şuna benziyor]. Bu, otomobillerin adlarını ve özelliklerini saklamak için böyle bir şeyle sonuçlanabileceğiniz anlamına gelir: "cars":{"ford":[8C,FA,BC,2A,384FFFFF],"holden":[00,00,04,FF,04FF54A9]}Hatta "otomobil" tanımlayıcısını atlayabilir ve otomobil alanının nerede olacağını biliyorsanız doğrudan bir diziye gidebilirsiniz. Eğer size bırakarak bu verileri kaydetmek gerek yok eğer "ford" ve "holden" isimleri ihmal bile edilebilir: [...,[[8C,FA,BC,2A,384FFFFF],[00,00,04,FF,04FF54A9]]]. Daha kompakt hale geliyor mu?
doppelgreener

1
@Axidos: İşaretlemeyi okunamaz ve yapılandırılmamış yapacaksanız, sadece ikili yapabilirsiniz. Bunun yanı sıra, çalışma zamanı sırasında sıkıştırılmamış verileri ayrıştırmamanız (bu durumda muhtemelen zaten vidalanmış olmanız) veya ayrıştırma sırasında bir şekilde birkaç yüz baytlık dize belleği için kısıtlanmamanız (yanlış bir şekilde mikrodalga, değilsiniz).

@Joe: bluescrn, yinelenen adlara sahip olmayan okunabilir bir format arıyor gibi görünüyor. JSON'un tam da bunu sunabilme yeteneğini gösteriyordum. Kesinlikle katılıyorum, belirli bir noktada neden böyle bir işaretleme ile uğraştığınızı bile merak edebilirsiniz.
doppelgreener

4

JSON kullanın.

(Munificent'in yanıtı ve büyük ölçüde başka yerlerde ifade edilen endişelerinize yanıt olarak)

JSON'un XML gibi alan adlandırma öğelerini boşa harcaması sorunundan bahsettiniz. Öyle değil.

JSON iki yapı üzerine kurulmuştur: ad / değer çiftleri ( nesneler ) ve sıralı değer listeleri ( diziler ). XML yalnızca ad / değer çiftleri üzerine kuruludur .

JSON'un, kendiniz açıklayıcı ve insan tarafından okunabilir olacak şekilde oluşturulmuş JSON'u okuduğunuz nesnelere dayandığını düşünüyorsanız, bu şekilde (tek baytları temsil etmek için sekizli basamak çiftlerini kullanarak):

{
    "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}
    ]
}

Bununla birlikte, her şeyin nerede olacağını bildiğiniz sürece, bu şekilde yazma seçeneğiniz de vardır (ve otomobil listenizi almak için "otomobil" yerine nesne 4 yerine dizin 4'ü arayabilirsiniz):

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

O yalnızca çok özlü olsun mu [, ], ,ve değerler?

Saf bir ikili akışa daha da yakınlaşmaya istekliyseniz olur.

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

Çok fazla optimizasyon yaparak kendinizi bacağınıza vurmayın.


2

Bir yanıtı kabul ettiğinizi biliyorum, ancak Google hem "Hızlı Bilgi Seti" (ikili XML) hem de vtd-xml.

(VTD) ikincisi XML kullanımının sıkıştırma yönünü çözmek olmayabilir rağmen, önemli ölçüde (kullandığı, büyük dosyalar arasında düğüm erişimi hızlandıracak bir ikili uzaklıklar 'sözlük' düğümler atlamak için ve yok her düğüm için nesneleri oluşturmak bunun yerine orijinal XML dizesinde çalışın). Bu nedenle, XML aramasının hem daha hızlı olduğu söylenir ve XML dokümana erişmek / işlemek için çok fazla işlem içi bellek gerektirmez.

Yukarıdakilerin her ikisinin de popüler dillerde (C # içeren) bağları vardır.

Şerefe

Zengin


1

Karvonite'i deneyebilirsiniz . Çevik olması gerekiyordu. Bu, verilerinizdeki değişikliklere oldukça iyi uyum sağlayacak bir kalıcılık çerçevesidir (ki bu, kendiniz ikiliyi işlemeye kıyasla güzeldir). Aslında verilerin nasıl yapılandırıldığından emin değilim, ancak dosyalar xml şişirilmiş dosyalardan çok daha küçük. (Verileri xml gibi metin yerine ikili biçimde kaydettiğini varsayıyorum)

Bununla birlikte düşünebileceğim tek şey, verileriniz bozulursa veya Karvonite'ın beğenmediği bir şekilde nasıl dağınıksa, yapısının nasıl yapıldığını anlamazsanız veri işleri.

Verilerinizi nasıl kaydedeceğinizi / yükleyeceğinizi belirtme şekliniz, kalıcılık düzenleyicisini açmanız, tüm veri nesneleriyle derlemenizi içe aktarmanız ve hangi nesneleri desteklemenizi istediğinizi ve hangi alanları / özellikleri kaydedeceğinizi göstermek için bazı onay kutularını işaretlemenizdir.

Denemeye değer olabilir. C # kullandığınızdan bu yana, XNA (Windows, Xbox360 ve iPhone'dan bahsettiğinizden beri ilginizi çektiğini düşündüğüm Windows Phone 7) ile çalıştığı için dilinize tam olarak uyuyor.

Düzenleme: Sadece araçları için sadece C # kullanarak fark ettim. Bu muhtemelen iş akışınıza çok iyi uymayacaktır. Nedense kafamda XNA vardı.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.