Estou trabalhando em uma ferramenta de edição de nível que salva seus dados como XML.
Isso é ideal durante o desenvolvimento, pois é indolor fazer pequenas alterações no formato dos dados e funciona bem com dados do tipo árvore.
A desvantagem, porém, é que os arquivos XML estão bastante inchados, principalmente devido à duplicação de nomes de tags e atributos. Também devido aos dados numéricos ocuparem muito mais espaço do que o uso de tipos de dados nativos. Um pequeno nível pode facilmente terminar em 1Mb +. Quero reduzir esses tamanhos significativamente, principalmente se o sistema for usado para um jogo no iPhone ou em outros dispositivos com memória relativamente limitada.
A solução ideal, para memória e desempenho, seria converter o XML em um formato de nível binário. Mas eu não quero fazer isso. Eu quero manter o formato bastante flexível. O XML facilita muito adicionar novos atributos aos objetos e atribui a eles um valor padrão se uma versão antiga dos dados for carregada. Então, eu quero manter a hierarquia de nós, com atributos como pares nome-valor.
Mas preciso armazenar isso em um formato mais compacto - para remover a duplicação maciça de nomes de tags / atributos. Talvez também para atribuir tipos nativos aos atributos, portanto, por exemplo, dados de ponto flutuante são armazenados como 4 bytes por flutuador, não como uma sequência de texto.
O Google / Wikipedia revela que 'XML binário' dificilmente é um problema novo - já foi resolvido várias vezes. Alguém aqui tem experiência com algum dos sistemas / padrões existentes? - é ideal para o uso de jogos - com uma biblioteca de analisador / carregador gratuita, leve e multiplataforma (C / C ++) disponível?
Ou devo reinventar essa roda eu mesmo?
Ou será melhor esquecer o ideal e apenas compactar meus dados .xml brutos (eles devem se compactar bem com a compactação do tipo zip) e apenas carregar a memória / desempenho em carga?
fonte
Respostas:
Usamos muito o XML binário para Superman Returns: The Videogame . Estamos falando de milhares e milhares de arquivos. Funcionou bem, mas honestamente não parecia valer a pena. Ele consumiu uma fração perceptível do nosso tempo de carregamento, e a "flexibilidade" do XML não aumentou. Depois de um tempo, nossos arquivos de dados tinham muitos identificadores estranhos, referências externas que precisavam ser mantidas em sincronia e outros requisitos estranhos para que eles fossem realmente editáveis por humanos.
Além disso, o XML é realmente um formato de marcação, e não um formato de dados. É otimizado para muito texto com tags ocasionais. Não é ótimo para dados totalmente estruturados. Não foi minha decisão, mas se tivesse sido e eu soubesse o que sei agora, provavelmente teria feito JSON ou YAML. Ambos são concisos o suficiente para não exigir compactação e são otimizados para representar dados , não texto .
fonte
Armazene e edite seus níveis como XML normal, mas faça com que seu mecanismo de jogo prenda-o lentamente em XML binário durante o carregamento e salve o XML binário de volta no disco para que possa carregar na próxima vez (se o XML bruto não tiver sido alterado) .
Algo assim:
Dessa forma, você obtém o melhor dos dois mundos. No lançamento, você só precisa garantir que todos os arquivos binários estejam lá.
fonte
Os buffers de protocolo do Google parecem ser o caminho a seguir, mas eu não os usei.
http://code.google.com/p/protobuf/
Você define um arquivo .proto que descreve o formato do arquivo:
Isso é compilado com uma ferramenta de linha de comando que gera classes C / C ++ para gravar e analisar arquivos de dados binários no formato de dados definido anteriormente. Existem também algumas extensões para diferentes linguagens de programação.
A desvantagem do ProtocolBuffer é que eles não são um formato de texto sem formatação. Você precisaria de uma ferramenta para gerá-los, ler e editá-los. Mas isso não deve ser um problema se você os estiver usando apenas para trocar dados entre o editor do jogo e o jogo. Eu não o usaria para definir arquivos de configuração;)
A compactação dos arquivos xml brutos também deve funcionar. Que tipo de jogo você está fazendo? Se for baseado em nível, você deverá carregar todos os recursos necessários apenas uma vez quando o nível for carregado.
atualização: existem vários projetos para outros idiomas, como o C #, para trabalhar com ProtocolBuffers:
http://code.google.com/p/protobuf/wiki/ThirdPartyAddOns
fonte
.proto
arquivo, que quase elimina problemas de falta de comunicação. Os protótipos são muito mais fáceis de ler / manter do que um esquema xml, se você tiver a disciplina (e tempo) para usar esquemas xml.E o formato JSON?
http://www.json.org/xml.html
fonte
"cars":{"ford":[8C,FA,BC,2A,384FFFFF],"holden":[00,00,04,FF,04FF54A9]}
você pode até omitir o identificador "cars" e ir direto para uma matriz se souber onde será o campo dos carros. Você mesmo pode omitir o "Ford" e nomes "Holden" se você não precisa salvar os dados, deixando-o com:[...,[[8C,FA,BC,2A,384FFFFF],[00,00,04,FF,04FF54A9]]]
. Fica mais compacto?Use JSON.
(Com base na resposta da Munificent e em grande parte em resposta às suas preocupações expressas em outros lugares)
Você mencionou a preocupação de que o JSON tenha o problema de desperdiçar elementos de nomeação de espaço, como XML. Não faz.
O JSON é construído em duas estruturas: pares nome / valor ( objetos ) e listas ordenadas de valores ( matrizes ). XML é criado apenas em pares nome / valor.
Se você acha que o JSON depende de objetos que você leu, ele foi desenvolvido para ser auto-descritivo e legível por humanos, como este (usando pares de dígitos octais para representar bytes únicos):
No entanto, você também tem a opção de escrevê-lo dessa maneira, desde que saiba onde tudo estará (e assim possa procurar o índice 4, em vez de objetos "carros", para obter sua lista de carros):
Será que ela obtenha mais conciso do que apenas tendo
[
,]
,,
e seus valores?Bem, isso acontece se você estiver disposto a se aproximar cada vez mais de um fluxo binário puro.
Apenas não atire na perna otimizando demais.
fonte
Sei que você aceitou uma resposta, mas o Google "Fast Infoset" (XML binário) e vtd-xml.
Embora o último (VTD) possa não resolver o aspecto da compactação do uso de XML, ele pode acelerar o acesso ao nó em arquivos grandes, consideravelmente (ele usa um 'dicionário' de deslocamentos binários para ir para os nós e não cria objetos para cada nó , trabalhe na sequência XML original). Portanto, sua pesquisa em XML é [mais rápida] e não requer tanta memória em processo para acessar / manipular o documento XML.
Ambos os itens acima têm ligações nos idiomas populares (que incluem C #).
Felicidades
Rico
fonte
Você poderia tentar o Karvonite . É para ser ágil. É uma estrutura de persistência que se adaptará às alterações em seus dados razoavelmente bem (o que é bom comparado a lidar com você mesmo). Na verdade, não tenho certeza de como os dados estão estruturados, mas os arquivos são muito menores que os arquivos inchados de xml. (Presumo que ele salve os dados em um formato binário em vez de texto como xml)
A única maneira de pensar com isso é que, se seus dados são corrompidos ou um pouco confusos de uma maneira que a Karvonite não gosta, você fica à mercê de seus criadores, a menos que você descubra como a estrutura do dados funcionam.
A maneira como você especifica como salvar / carregar seus dados é apenas abrir o editor de persistência, importar sua montagem com todos os objetos de dados e marcar algumas caixas de seleção para mostrar quais objetos você deseja suportar e quais campos / propriedades salvar.
Pode valer a pena uma tentativa. Desde que você usa C #, isso se encaixa perfeitamente no seu idioma, pois funciona com o XNA (Windows, Xbox360 e Windows Phone 7, no qual acho que você está interessado desde que mencionou o iPhone?).
Edit: Acabei de notar que você está usando apenas C # para as ferramentas. Isso provavelmente não se encaixaria muito bem no seu fluxo de trabalho. Por alguma razão, eu tinha XNA na minha cabeça.
fonte