Sign in to follow this  
Angelic Ice

Saving frequently

Recommended Posts

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 : )

Edited by Angelic Ice

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites

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.

Edited by Norman Barrows

Share this post


Link to post
Share on other sites

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

Edited by L. Spiro

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this