- Home /
Saving My World
I'm making a 2D Minecraft or Terraria style game and I've started to make a terrain generation script. If your not aware Minecraft uses blocks as it's level geometry. My problem is that when saving out each of my blocks to an XML file it take sooooooo long! All I'm doing is writing three things to the file: posX, posY and blockType. If I save a world this big then it takes 20 seconds! Now that world was about 640 blocks and obviously way to small for an actual world. It was only 20 blocks across and 32 down.
Now I thought about what the problems could be like maybe it's because I'm instantiating so many blocks at one time and that could have an effect on the time it takes for the world the save out. However that is not the case, I ran the same test with the same amount of blocks only this time didn't instantiate anything just wrote to the file. The time it took was the exact same. I don't think that instantiating so many blocks even really is that hard on the engine considering that I can generate a world this big (without saving of course) without any problems. That world was about 12,800 blocks (400 x 32). God knows how long it would take to save that world at my current rate!
So whats the problem here? Why does it take so long to save a world by writing to a XML file? I'm I going about this wrong? Please help me out!
EDIT: Here is a screen shot of my XML file for the 640 block world in case you were curious on how I'm structuring it.
Answer by Eric5h5 · Oct 29, 2011 at 08:43 PM
I would not recommend using XML like that. It would be better if you just saved the raw data, since it's a huge waste of space to have <block><position>
etc. for each block. In any case all you need to save is the dimensions of the world and the type of each block, you don't need to save the coordinates, so it would be at least a 50X smaller file size overall if you just saved the block types and didn't use XML. Also it would be a lot more efficient to construct the world as a mesh or series of meshes (considering each mesh is limited to ~64K verts and it would be better to use ~20K) rather than having a GameObject for each block.
What do you mean save the raw data? I can't just save the dimensions of a world because later on I'm going to add caves and saving the dimensions would just be a large rectangle.
Also you say I shouldn't use X$$anonymous$$L but then what should I use? I have to read and write something to a file in order to save and load a world.
Lastly about saving the world as a mesh, I have no idea what your talking about I need a mesh for each block in order to manipulate it.
$$anonymous$$aybe I wasn't clear enough, I should also point out that the player will be able to destroy and place blocks just like $$anonymous$$inecraft. So I need a way to quickly find a block at the position the player digs and remove it from the save file. Same thing with placing (that's why I save the position of each block). I need quick access which is one of the reason why I chose X$$anonymous$$L. Also because it's designed for storing data.
Could you just go into more detail? Sorry I'm just really stumped on what to do. I would really appreciate it.
By save the dimensions I mean include 20x32 (or whatever) as part of the data, so you know that the world should be 20 across by 32 down. Otherwise you wouldn't know how the 640 blocks are arranged--it could be 2x320, 4x160, and so on. It's also a sort of checksum, so you know there's supposed to be 20x32 entries in the file, and if there aren't, then something is wrong.
As for raw data, I mean raw data. Bytes. If there are fewer than 257 types of blocks, then just save 1 byte per block. Then the file would be a total of 640 bytes + whatever it takes to store the "20x32" part (you could have the first two bytes be the width and the second two bytes be the height, as long as you're not planning on having levels bigger than 65536x65536, so in this case the total would be 644 bytes). If you need quick access, X$$anonymous$$L isn't going to help, and speed is meaningless for such small amounts of data anyway, since saving the file is going to be pretty much instant, plus you're going to be manipulating the data in memory, with saving only being done occasionally. X$$anonymous$$L isn't designed for storing data like this...as I mentioned, it's a ridiculously huge waste of resources. If you really want to use X$$anonymous$$L, you could have an entry for width, an entry for height, and then an entry for the binary level data (probably stored with Base64), but it seems pointless for simple data like this.
Ok I think I'm understanding this a little bit better.
Let's use a world of 5x5 for an example. Are you saying I should have 5 entries horizontally and 5 entries vertically and make the entries a integer to show the block type? i.e. 0 for dirt, 1 for stone, ect... So the file would look like: http://i.imgur.com/lp7$$anonymous$$x.png I guess I could use 0 to show that there isn't a block there perhaps? So when loading the blocks the parser would skip it. This would allow for caves and other holes in the world.
Is that what you were talking about? I think this is a great idea if it's what you were talking about or not.
Also one more quick question that wasn't answered: What should the file extension be?
A byte rather than an integer (which is 4 bytes so is probably major overkill), but otherwise basically yes. The entries don't have to be arranged in the file in a 5x5 layout, although that's a valid way of storing things too. Putting all the data in one lump and including the width and height information would be the most efficient way to store the data, but having each line of the file represent a row wouldn't be that much less efficient. The file extension can be whatever you want (including nothing), but it would probably be a good idea to come up with something unique.
If you going to do that then your save files could be pretty big. Consider $$anonymous$$indcraft probably has something like 10,000 x 10,000 and with considerable height , say a 5,000. But lets pretend its small like 1,000 x 1,000 x 1,000 - thats still close to 1GB save file. As it stands this just wouldnt be workable.
You need to think about encoding this more intelligently. I would use a double byte; the first byte tells you how many of the following character there will be and the second byte will be the map item itself. This means when you have strips of similar material you will gain massively in the amount of space it takes.
The next thing you may need to consider is that actually a single byte probably wont be enough to describe absolutely anything you want. In which case I would make that byte extensible by using the most significant bit as continuation character. So make sure your most common materials are in the first 127.
Your answer
Follow this Question
Related Questions
Write to XML-file within Assets\Resources 1 Answer
Using XML for a simple webplayer Highscore Table 1 Answer
Write and Read to a iOS device! Help 1 Answer
Editing an XML File 1 Answer
System.IO documentation? 2 Answers