게임 데이터를위한 '바이너리 XML'?


17

데이터를 XML로 저장하는 레벨 편집 도구를 개발 중입니다.

이는 데이터 형식을 약간 변경하는 것이 번거롭지 않고 개발 과정에서 이상적이며 트리와 같은 데이터와 잘 작동합니다.

그러나 단점은 XML 파일이 태그와 속성 이름이 중복되어 다소 부풀어 있다는 것입니다. 또한 숫자 데이터가 기본 데이터 유형을 사용하는 것보다 훨씬 더 많은 공간을 차지하기 때문입니다. 작은 레벨은 1Mb +로 쉽게 끝날 수 있습니다. 특히 시스템이 메모리가 상대적으로 제한된 iPhone 또는 기타 장치의 게임에 사용되는 경우이 크기를 크게 줄이려고합니다.

메모리와 성능을위한 최적의 솔루션은 XML을 이진 수준 형식으로 변환하는 것입니다. 그러나 나는 이것을하고 싶지 않습니다. 형식을 상당히 유연하게 유지하고 싶습니다. XML을 사용하면 객체에 새 속성을 매우 쉽게 추가 할 수 있으며 이전 버전의 데이터가로드되는 경우 기본값을 제공합니다. 따라서 속성을 이름 값 쌍으로 사용하여 노드 계층 구조를 유지하려고합니다.

그러나 태그 / 속성 이름의 대규모 중복을 제거하기 위해 이것을보다 컴팩트 한 형식으로 저장해야합니다. 예를 들어 부동 소수점 데이터는 텍스트 문자열이 아닌 부동 소수점 당 4 바이트로 저장됩니다.

구글 / 위키피디아는 '이진 XML'이 새로운 문제가 아니라는 사실을 밝혀 냈습니다. 이미 여러 차례 해결되었습니다. 여기에 기존 시스템 / 표준에 대한 경험이있는 사람이 있습니까? -무료, 경량 및 크로스 플랫폼 파서 / 로더 라이브러리 (C / C ++)를 사용할 수있는 게임에 이상적입니까?

아니면이 바퀴를 다시 발명해야합니까?

아니면 이상적인 것을 잊어 버리고 원시 .xml 데이터를 압축하고 (zip과 같은 압축으로 압축해야 함)로드시 메모리 / 성능 히트를 취하는 것이 더 좋습니까?


1
XML은 GZIP 등 사용하여 압축 할 수있다 아주 잘.
ThiefMaster

답변:


18

우리는 Superman Returns : The Videogame에 바이너리 XML을 많이 사용했습니다 . 우리는 수천의 파일을 이야기하고 있습니다. 정상적으로 작동했지만 솔직히 노력할 가치가 없었습니다. 로딩 시간의 눈에 띄는 부분을 차지했으며 XML의 "유연성"은 확장되지 않았습니다. 잠시 후, 데이터 파일에 이상한 식별자, 동기화해야하는 외부 참조 및 더 이상 사람이 편집 할 수있는 기타 이상한 요구 사항이 너무 많습니다.

또한 XML은 실제로 데이터 형식이 아니라 마크 업 형식입니다. 가끔 태그가있는 많은 텍스트에 최적화되어 있습니다. 완전히 구조화 된 데이터에는 적합하지 않습니다. 그것은 내 전화가 아니었지만 지금까지 알고 있었고 지금 알고있는 것을 알고 있다면 JSON 또는 YAML을했을 것입니다. 둘 다 압축이 필요하지 않을 정도로 간결하며 text가 아닌 데이터 를 표현하는 최적화되어 있습니다.


1
BSON 이라는 바이너리 버전의 JSON이 있습니다 .
Philipp

12

레벨을 일반 XML로 저장 및 편집하되 게임 엔진이로드하는 동안 이진 XML로 느슨하게 구워 내고 이진 XML을 디스크에 다시 저장하여 다음 번에로드 할 수 있도록합니다 (원시 XML이 변경되지 않은 경우). .

이 같은:

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

그렇게하면 두 세계를 최대한 활용할 수 있습니다. 릴리스시 모든 바이너리 파일이 있는지 확인하면됩니다.


5

Google 프로토콜 버퍼는 갈 길처럼 보이지만 직접 사용하지는 않았습니다.
http://code.google.com/p/protobuf/

파일 형식을 설명하는 .proto 파일을 정의하십시오.

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

그런 다음 이전에 정의 된 데이터 형식으로 이진 데이터 파일을 작성하고 구문 분석하기 위해 C / C ++ 클래스를 생성하는 명령 행 도구로 컴파일됩니다. 다른 프로그래밍 언어를위한 확장 기능도 있습니다.

ProtocolBuffer의 단점은 일반 텍스트 형식이 아니라는 것입니다. 생성, 읽기 및 편집 도구가 필요합니다. 그러나 게임 에디터와 게임간에 데이터를 교환하기 위해 사용하는 경우에는 문제가되지 않습니다. 구성 파일을 정의하는 데 사용하지는 않습니다.)

원시 xml 파일을 압축해도 작동합니다. 어떤 종류의 게임을 만들고 있습니까? 레벨 기반 인 경우 레벨을로드 할 때 필요한 모든 자원을 한 번만로드해야합니다.

업데이트 : C #과 같은 다른 언어를 위해 ProtocolBuffers와 함께 작동하는 몇 가지 프로젝트가 있습니다 :
http://code.google.com/p/protobuf/wiki/ThirdPartyAddOns


시리얼 라이저가 이런 종류의 문제에 적합하지 않습니까? 나는 추측하지 않지만 분명한 차이는 보이지 않습니다. 그러나 나 에게이 대답은 적절 해 보입니다. 그러나 tar / gzip xml 파일은 텍스트이므로 크기가 크게 줄어 듭니다 (텍스트이므로 XML에서도 작동한다고 생각합니다). "더 쉬운"솔루션 일 수 있습니다. 어쨌든 XML은 쉬운 언어이지만 구문 분석 / 메모리 사용 측면에서 비용이 많이 듭니다. XML을 사용할 때는 가능한 한 몇 번 읽고 쓰십시오.
jokoon

흥미로운 옵션이지만 파이프 라인의 어느 곳에서나 XML을 사용하는 완전한 대안처럼 보입니다. 솔직히 말해서, 나는 생성 된 코드에 대해 열광적이지 않습니다. 또 다른 문제는 도구 측면에서 C #을 사용하고 있다는 것입니다 (도구가 큰 .XML 파일을 계속 사용하는 것이 행복합니다) ). XML-> PB 변환기는 옵션 일 수 있지만 특정 '이진 수준 데이터'를 굽는 방법보다는 여전히 '일반 목적 이진 XML'인 것을 찾고 있다고 생각합니다. 효율적)
bluescrn

"저는 도구 측면에서 C #을 사용하고 있습니다"라는 C # 프로젝트가 여러 개 있습니다. 내 답변을 업데이트했습니다.
Stephen

@ bluescrn, 생성 된 코드에 대해 너무 걱정하지 않아도됩니다. Google은 C ++, Java 및 Python을 1 등석으로 지원합니다. 그들은 내부적으로 광범위하게 사용합니다. 생성 된 코드는 매우 강력합니다. PB의 큰 장점 중 하나는 .proto파일 에 대한 도구 프로그램으로 , 통신 문제를 거의 제거 할 수 있다는 것입니다. XML 스키마를 사용하는 훈련 (및 시간)이있는 경우 프로토 타입은 XML 스키마보다 훨씬 쉽게 읽고 유지 관리 할 수 ​​있습니다.
deft_code

4

JSON 형식은 어떻습니까?

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


XML보다 약간 간결 해 보이지만 여전히 중복 된 속성 이름 문제가 있습니다. 파일에 'XPosition', 'YPosition'및 'Scale'속성이있는 게임 오브젝트 목록이 포함 된 경우 문자열 'XPosition'/ 'YPosition'/ 'Scale'은 모든 단일 게임 오브젝트에 대해 복제됩니다. 이것이 내가 현재 '압축'을 목표로하는 주요한 것입니다.
bluescrn

1
@ bluescrn : 아니요, 해당 문제가 없습니다. 객체는 하나의 구조입니다. 당신은 또한 배열을 사용할 수 있습니다. 즉, 자동차의 이름과 속성을 저장하기 위해 다음과 같은 결과를 "cars":{"ford":[8C,FA,BC,2A,384FFFFF],"holden":[00,00,04,FF,04FF54A9]}얻을 수 있습니다. "자동차"식별자를 생략하고 자동차 필드가 어디에 있는지 알면 바로 배열로 이동할 수 있습니다. 해당 데이터를 저장할 필요가 없으면 "ford"및 "holden"이름을 생략해도 [...,[[8C,FA,BC,2A,384FFFFF],[00,00,04,FF,04FF54A9]]]됩니다. 더 컴팩트 해 집니까?
doppelgreener

1
@Axidos : 읽을 수없고 구조화되지 않은 마크 업을 만들려면 이진으로 만들 수도 있습니다. 그 외에도 런타임 중에 압축되지 않은 데이터를 구문 분석하지 않거나 (어쨌든 망할 수도 있습니다) 구문 분석 중에 수백 바이트의 문자열 메모리로 제한되지 않는 한 잘못된 절약입니다. 전자 레인지는 아닙니다).

@Joe : bluescrn이 중복 된 이름이없는 읽을 수있는 형식을 찾고있는 것 같습니다. 나는 그것을 제공하는 JSON의 능력을 설명했다. 나는 특정 시점에서 왜 당신이 왜 이런 마크 업으로 귀찮게하는지 궁금 할 것입니다.
doppelgreener

4

JSON을 사용하십시오.

(Munificent의 응답을 기반으로하며, 다른 곳에서 표현 된 귀하의 우려에 대한 응답으로)

JSON에 XML과 같은 공간 이름 지정 요소를 낭비하는 문제가 있다는 우려를 언급했습니다. 그렇지 않습니다.

JSON은 이름 / 값 쌍 ( 객체 )과 순서 값 목록 ( 배열 )의 두 가지 구조로 구축됩니다 . XML은 이름 / 값 쌍 에만 구축 됩니다 .

JSON이 객체에 의존한다고 생각한다면 JSON을 읽었으며 다음과 같이 자기 설명적이고 사람이 읽을 수 있도록 작성되었습니다 (8 바이트 숫자 쌍을 사용하여 단일 바이트를 나타냄).

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

그러나 모든 것이 어디에 있을지 알기 만하면 (차량 목록을 얻기 위해 객체 "cars"가 아니라 index 4를 찾을 수있는 한) 이와 같이 작성하는 옵션도 있습니다.

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

그냥하는 것보다 더 간결 얻는가 [, ], ,및 당신의 가치를?

순수 바이너리 스트림에 점점 더 가까워지고 싶다면 기꺼이하십시오.

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

너무 많이 최적화하여 다리에 쏘지 마십시오.


2

답변을 수락했지만 Google은 "Fast Infoset"(이진 XML) 및 vtd-xml을 모두 알고 있습니다.

후자 (VTD)는 XML 사용의 압축 측면을 해결하지 못할 수도 있지만 대용량 파일의 노드 액세스 속도를 크게 높일 수 있습니다 (이진 오프셋 '사전'을 사용하여 노드로 이동하고 각 노드에 대한 객체를 만들지 않습니다) 대신 원본 XML 문자열로 작업하십시오. 따라서 XML 조회가 더 빠르며 XML 문서에 액세스 / 조작하는 데 많은 프로세스 메모리가 필요하지 않습니다.

위의 두 가지 모두 널리 사용되는 언어 (C # 포함)로 바인딩되어 있습니다.

건배

풍부한


1

Karvonite 시도해 볼 수 있습니다. 민첩해야합니다. 데이터의 변경 사항에 상당히 잘 맞는 지속성 프레임 워크입니다 (바이너리 자체 처리와 비교할 때 좋습니다). 실제로 데이터가 어떻게 구성되어 있는지 잘 모르겠지만 파일은 xml bloated 파일보다 훨씬 작습니다. (XML과 같은 텍스트 대신 이진 형식으로 데이터를 저장한다고 가정합니다)

내가 이것에 대해 생각할 수있는 유일한 단점은 Karvonite가 그것을 좋아하지 않는 방식으로 데이터가 손상되거나 일부 엉망이되면, 당신이 어떤 종류의 데이터가 작동합니다.

데이터 저장 /로드 방법을 지정하는 방법은 지속성 편집기를 열고 모든 데이터 개체와 함께 어셈블리를 가져오고 일부 확인란을 선택하여 지원하려는 개체와 저장할 필드 / 속성을 표시하는 것입니다.

시도해 볼 가치가 있습니다. C #을 사용하기 때문에 XNA (iPhone을 언급 한 이후 관심이 있다고 생각되는 Windows, Xbox360 및 Windows Phone 7)에서 작동하기 때문에 언어에 맞습니다.

편집 : 도구에 C # 만 사용하는 것으로 나타났습니다. 이것은 아마도 워크 플로에 잘 맞지 않을 것입니다. 어떤 이유로 나는 머리에 XNA가 있었다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.