38
\$\begingroup\$

I need to save some custom game data. Map, player, etc.

All of them will have "sub objects". For example, a map and map will have an "array" of tiles. ie, hierarchical data. Hopefully nothing binary.

What would be a good format for these?

So far I'ved considered:

Serailization: This is FAST and easy, but tends to break when I change the underlying classes :(

XML: I really hate parsing this. My test case was over 100+ lines of code and seemed likes tons of "busy work" for even a very simple format.

INI: would be really clumsy for hierarchical data.

Protobuf: Never used it, but read you have to do a lot of manual mucking around and breaks if you change the class.

Other options? That's why I'm here!

Edit: this is Java btw.

Edit 2:

I settled on "Controlled Binary Serialization" (see below).

Pros:

  • it's fast

  • it's small (on disk) and can be easily compressed/decompressed during read/write.

  • it's super easy to read/write from game and toolset.

  • I can decide what to include/exclude of the object.

  • Objects/Data can be nested.

Cons:

  • Can't edit it by hand (like XML, YAML, etc)

  • Can't easily read/modify it with scripts

  • Java Serialization by default is pretty slow/bloated compared to other implentations, but it's stable and works

\$\endgroup\$
6
  • 3
    \$\begingroup\$ comma separated values \$\endgroup\$ Commented Oct 26, 2011 at 19:55
  • \$\begingroup\$ @trinithis KISS is a great thing. \$\endgroup\$
    – Nate
    Commented Oct 27, 2011 at 6:06
  • 3
    \$\begingroup\$ Don't fall into the trap that thinking CSV parsing is easy: secretgeek.net/csv_trouble.asp \$\endgroup\$
    – Tetrad
    Commented Oct 27, 2011 at 7:01
  • \$\begingroup\$ Funny, ProtoBuf was built to support upgradeability. \$\endgroup\$ Commented Nov 1, 2011 at 8:17
  • \$\begingroup\$ ini for everything user-modifiable like settings, etc; and binary for everything else. \$\endgroup\$ Commented Jul 12, 2015 at 19:24

6 Answers 6

39
\$\begingroup\$

To display hierachical data, YAML or JSON would be good options. They are far simpler and easier to parse than XML.

Another option would be a "controlled" binary serialization process. Every object writes it's state out in a controlled way, i.e.

void player::save(savegame &sgm)
{
    sgm.write(this->position);
    sgm.write(other properties);
    inventory.save(sgm);
}

id Tech 4 (Quake 4 / Doom 3 engine) uses such an approach.

\$\endgroup\$
8
  • \$\begingroup\$ +1 For "controlled" binary serialization. I use this at work and it's great! \$\endgroup\$ Commented Oct 26, 2011 at 19:53
  • 1
    \$\begingroup\$ Another +1 for "controlled" binary serialization. While I've never heard the name before, I do something similar in a few places - done right, it has the advantage of being able to set defaults for newly added fields that don't exist in the data file, and to ignore "junk" in the data file when a field is removed from the model. \$\endgroup\$
    – Izkata
    Commented Oct 26, 2011 at 20:28
  • \$\begingroup\$ I use something like this in my game. It works well! I use java. Each object has a ToByteStream method that writes to a file stream and a constructor that reads from a file stream. I didn't like Javas Serializable implementation. \$\endgroup\$
    – House
    Commented Oct 27, 2011 at 1:18
  • 4
    \$\begingroup\$ Or you could just use Boost.Serialize and get wonderful features like versioning and so forth. \$\endgroup\$ Commented Oct 27, 2011 at 5:20
  • \$\begingroup\$ @Izkata I've made that name up because I have no idea how this method is called. \$\endgroup\$
    – Raphael R.
    Commented Oct 27, 2011 at 11:06
10
\$\begingroup\$

A well made binary format has really got all the advantages, it's fast, reasonably small, and as flexible as you make it.

Making a binary format you are bound by no rules, which is a great advantage, but ironically it's largely what has given binary file structures a bad name. XML, JSON and the like makes a lot of decisions for you, they are far from always optimal, but they are reasonably safe choices that will usually help you steer clear of some otherwise common problems.

Identify these problems, design your format with those in mind, and you can make a great binary format.

If you are not experienced/confident enough to make a binary format and the amount of data is small enough that the speed impact will be negligible, I suggest that you use JSON, it's simple, but does the job.

\$\endgroup\$
8
\$\begingroup\$

Your choice of file format is hugely dependent on your current toolset and the game you are intending to make. With that said...

Toolset is one of the most important factors when deciding a game file format. If you make a binary format, you have to always ensure that you have the tools to input your game data. This could be as simple as a hex editor, or as complex as Unreal Editor.

I guess the main advantage of XML, YAML, or any other language files, is that you can edit it easily via a text editor. And using an existing standard, it ensures you can't go wrong. But, this is extremely tedious when you have a thousand files, which brings me to my next point.

Game. What kind of game are you making? Why I say this will affect the file format? Because, if you are making something like 2D bomberman, you could get away with a simple text file like:

*********
*1     2*    1,2,3,4  - start point of players 1, 2, 3, 4
* + + + *    *        - walls
*       *    +        - crates
* + + + *
*3     4*
*********

In other words, always go for the most obvious format for your specific data. RPGs are the most complex game genre to make. They require lots of data. But doesn't mean you have to stick a specific format, be it binary or text-based for all data in the game.

  • Maps, particles, and other graphical stuff tend to use a custom binary format. Because it's the simplest way to implement it. It's not humanly-sane to describe maps textually. Usually edited via map/level/particle editors.
  • Players, items, enemies, skills and quests are statistics that affect game balance. They usually require lots and lots of input and tweaking. I like to do this by putting it in an XML file for ease of implementation, but yet having an object editor for the designers to play with. Best of both worlds.

Generally, you want to describe text with a text format, and graphics with a binary format. The following should give you an example:

<Skill>
    <Name>Fireball</Name>
    <Animation>fireball.dat</Animation> <!-- Graphics described in another file -->
    <Attack>1.3</Attack>
    <Cooldown>15</Cooldown>
</Skill>

To sum it up, it is to my fullest recommendation that if possible, you don't script your data, unless absolutely necessary. The end-user doesn't care about how awesome the format is, as long as the game is playable, that's all that matters.

Cheers, roy =)

\$\endgroup\$
0
5
\$\begingroup\$

BSON is pretty nice. http://bsonspec.org/. It is easier to parse then JSON and better at containing binary data, but still has a nice structure. It's somewhat similar to protocol buffers. The downside is that there dosent seem to be a lot of tool support for it outside of mongodb.

EDIT: MsgPack ( http://msgpack.org/ ) is also similar to BSON and seem to be gaining more traction.

\$\endgroup\$
1
  • 2
    \$\begingroup\$ While I think that the idea of a "binary JSON" is good I have little faith in BSON, there are too many (redundant) data types, and the documentation sucks. \$\endgroup\$ Commented Oct 27, 2011 at 14:11
2
\$\begingroup\$

What's happened to your custom binary data format? If you are afraid of raw serialisation, write your own system that writes fields as needed, and reads them back. No need for xml, which is indeed overly bulky and complex for situations where you don't need the transparency the format provides. Just define a well-specified file format and stick to it, leaving maybe some room for expansion of your data set in each record by padding them with null values (say you have a 100 byte record now, pad that to 150 for future use.
Add a version number and maybe a checksum so you can know what fields should be filled and have a sanity check for validity, and you're good to go.

\$\endgroup\$
1
\$\begingroup\$

You can mix XML or some other format with Base64 insertions for some specific data, and for fields you need readability you can use usual TEXT

\$\endgroup\$

Not the answer you're looking for? Browse other questions tagged .