Saving frequently

Started by
5 comments, last by Kylotan 7 years ago

Hey forum : )

I wanted to know what I could do to provide a fluid and automated saving.

First, I do not want to frustrate my users by having the app crash. One reasoning could be Android's nature of closing/killing application that seem to idle. The easy solution would be, once my game loses focus, initiate a last save and then idle.

But what is when a random bug occurs and all progress is lost during gameplay? Additionally, I do not want to bother my player to think about saving.

So, this is how I structure my level-files at the moment: One Lua-table entry represents on entity/object and its attributes/components are further tables within the object. Every object is changing its state quite often. E.g. There are certain types of entities, so entity a and entity b share the same object-type x. Does not mean, that there is no object-type y.

I deserialise my entities and their components to C++-objects. In order to save, I would have to serialise them and write the entire file again. As I want to save frequently (about after every move/change the player commits), I thought about ways to make serialise small changes faster.

One idea was, to make the actual level-file contain only references to current entities. E.g.


local objects
{
reference[1] = "object_a_1.lua",
reference[2] = "object_a_2.lua",
reference[3] = "object_a_3.lua",
reference[4] = "object_b_1.lua",
reference[5] = "object_b_2.lua"
}

Could also drop the .lua-suffix, of course. Then, I could move the current instance/state of each object into their own file. Each C++-object would just have a reference to that object-instance-file and write changes to their equivalent.

What would your take-on be if you want to save frequently without any interrupt? We are talking about small changes and few changes per user-interaction. Is there any common practice?

I mean, I do not have to save every single action, but would like to do so in reasonable portions. This game is working on Android, Windows and Linux.

Thanks for your time, have a great day : )

Advertisement

What would your take-on be if you want to save frequently without any interrupt? We are talking about small changes and few changes per user-interaction. Is there any common practice?

Depending on your needs an in-progress save can be quite difficult.

It is a relatively easy thing to restore a level from scratch; just load the level.

It is another thing altogether to restore in progress. That can mean mid-interaction, mid-animation, mid-audio, mid-effect.

For some games it isn't that bad. A match three style game can record the current board, the scores and timers, and it is done. For others the process is quite difficult, so they restore from a waypoint, or restore from the last level started. For many games with very short levels, they record the data when you complete a level but otherwise don't bother to restore at all

Bear in mind that Android has a very specific system for dealing with activities going out of action and potentially being destroyed. Look up 'onSaveInstanceState', for example.

The main thing any developer can do to speed up save games is to make sure they are never saving or writing anything that does not change. Clearly separate static data like textures, meshes, and character archetypes from dynamic data like positions, events, and current character status.

I wouldn't recommend trying to save into multiple files; that is often slower, and leaves you open to inconsistency problems.

To maximize saving speed:

1. save only what you must. the fastest kind of variable to save is one you never save at all. designing your game so it can pickup where it left off with minimal info helps.

2. use a single file. opening multiple files takes more time.

3. use binary files (fast) as opposed to text files (slow).

4. write a whole buffer at once (such as a meg), instead of individual variables.

5. use a fast low level write routine such as _fwrite_nolock()

In Caveman 3.0, i can save 97 meg in a couple seconds without buffering, just writing individual variables. _fwrite_nolock() seems to be the key to accomplishing this.

Norm Barrows

Rockland Software Productions

"Building PC games since 1989"

rocklandsoftware.net

PLAY CAVEMAN NOW!

http://rocklandsoftware.net/beta.php

Use file-mapping and update only what needs to be updated. You can keep the file map open as long as you please (during the entire session or just when saving) and it should never be possible for the file to simply vanish even through crashes.


L. Spiro

I restore Nintendo 64 video-game OST’s into HD! https://www.youtube.com/channel/UCCtX_wedtZ5BoyQBXEhnVZw/playlists?view=1&sort=lad&flow=grid

Thanks for all your answers : )

Bear in mind that Android has a very specific system for dealing with activities going out of action and potentially being destroyed. Look up 'onSaveInstanceState', for example.

Yes, thanks for pointing out, though : )

I wouldn't recommend trying to save into multiple files; that is often slower, and leaves you open to inconsistency problems.

Hm, but then I would have to write the whole savegame-file for every little change, even if only one value changes (assuming automatic saving after every change).

3. use binary files (fast) as opposed to text files (slow).

Ah, totally forgot to do that, thanks for reminding me : )

Use file-mapping and update only what needs to be updated. You can keep the file map open as long as you please (during the entire session or just when saving) and it should never be possible for the file to simply vanish even through crashes.

Not sure if I really understands the advantage or the concept itself. Wouldn't that still require to write the entire level-file? How would I only update what is needed, if that requires to write my whole file again?

The general issue is, that the changes are very small per user-action, but that still would make me need to update a huge level-file.

Just an example: It is like rotating a 2d-brick by 90° and then saving this. It would also require to serialise all my other brick C++ objects back to a Lua-table - upon every single change.

That is why I thought putting them in separated file would support partial updating. It would slow loading though.

I wouldn't assume automatic saving after every change. You don't really need to do that. You get notified when an app is closing or the computer is shutting down. And as for crashes, the best thing is to fix your crashes.

If you really need a system that allows many incremental saves, then that already exists and is called a database: Sqlite will do that, on all those platforms. It will work for you, if you refactor your save data into a relational form.

This topic is closed to new replies.

Advertisement