Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unity/C# Savegame Migration

I've written a SaveLoad class, which contains a Savegame class that has a bunch of ints, doubles, bools but also more complex things like an array of self-written class objects.

That savegame object is being created, serialized and AES encrypted on save and vice versa on load - so far, so good.

The problem I'm facing now is that if there are new variables (in a newer version of the game) that have to be stored and loaded, the game crashes on load, because the new variables can't be loaded correctly (because they are not contained in the old save file). E.g. ints and doubles contain the default 0 while an array is not initialized, thus null.

My current "solution": For each variable that is being loaded, check if it doesn't contain a specific value (which I set in the Savegame class). For example: In Savegame I set

public int myInt = int.MinValue;

and when loading, I check:

if(savegame.myInt != int.MinValue){
    //load successful
}else{
    //load failed
};

This works so far for int and double, but once I hit the first bool, I realized, that for every variable I have to find a value that makes "no sense"(not reachable usually), thus was a failed load. => Shitty method for bools.

I could now go ahead and convert all bools to int, but this is getting ugly...

There must be a cleaner and/or smarter solution to this. Maybe some sort of savegame migrator? If there is a well done, free plugin for this, that would also be fine for me, but I'd prefer a code-solution, which may also be more helpful for other people with a similar problem.

Thanks in advance! :)

like image 809
Tavados Avatar asked Jul 24 '26 11:07

Tavados


1 Answers

Your issue is poor implementation.

If you are going to be having changes like this, you should be following Extend, Deprecate, Delete (EDD).

In this case, you should be implementing new properties/fields as nullables until you can go through and data repair your old save files. This way, you can check first if the loaded field is null or has a value. If it has a value, you're good to go, if it's null, you don't have a value, you need to handle that some way.

e.g.

/*We deprecate the old one by marking it obsolete*/
[Obsolete("Use NewSaveGameFile instead")]
public class OldSaveGameFile
{
    public int SomeInt { get; set; }
}

/*We extend by creating a new class with old one's fields*/
/*and the new one's fields as nullables*/
public class NewSaveGameFile
{
    public int SomeInt { get; set; }
    public bool? SomeNullableBool { get; set; }
}

public class FileLoader
{
    public SavedGame LoadMyFile()
    {
        NewSaveGameFile newFile = GetFileFromDatabase(); // Code to load the file
        if (newFile.SomeNullableBool.HasValue)
        {
            // You're good to go
        }

        else
        {
            // It's missing this property, so set it to a default value and save it
        }
    }
}

Then once everything has been data repaired, you can fully migrate to the NewSaveGameFile and remove the nullables (this would be the delete step)

like image 181
Stephen P. Avatar answered Jul 26 '26 02:07

Stephen P.