Unity / C#Savegame Migration

时间:2016-09-28 20:51:12

标签: c# unity3d unity5

我写了一个SaveLoad类,其中包含一个Savegame类,它包含一堆int,double,bools以及更复杂的东西,比如一组自编的类对象。< / p>

该savegame对象正在创建,序列化和AES加密保存,反之亦然 - 到目前为止,非常好。

我现在面临的问题是,如果有新的变量(在较新版本的游戏中)必须存储和加载,游戏会在加载时崩溃,因为新变量无法正确加载(因为它们不包含在旧的保存文件中)。例如。 int和double包含默认值0,而数组未初始化,因此为null。

我当前的“解决方案”:对于正在加载的每个变量,检查它是否不包含特定值(我在Savegame类中设置)。 例如:在Savegame我设置

public int myInt = int.MinValue;

加载时,我检查:

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

到目前为止这对于int和double来说是有效的,但是一旦我遇到第一个bool,我意识到,对于每个变量,我必须找到一个“无意义”的值(通常不可达),因此是一个失败的负载。 =&GT;粗暴的方法。

我现在可以继续将所有bools转换为int,但这很难看......

必须有一个更清洁和/或更智能的解决方案。也许是某种游戏移民?如果有一个做得好的免费插件,对我来说也没关系,但我更喜欢代码解决方案,对于遇到类似问题的其他人来说也可能更有帮助。

提前致谢! :)

2 个答案:

答案 0 :(得分:1)

您的问题是执行不力。

如果你要进行这样的更改,你应该关注Extend,Deprecate,Delete(EDD)。

在这种情况下,您应该将新属性/字段实现为nullables,直到您可以对旧的保存文件进行数据修复。这样,您可以首先检查加载的字段是否为空或具有值。如果它有一个值,你很高兴,如果它是null,你没有值,你需要以某种方式处理。

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
        }
    }
}

然后,一旦所有数据都被修复,您就可以完全迁移到NewSaveGameFile并删除nullables(这将是删除步骤)

答案 1 :(得分:0)

因此,一种解决方案是将保存文件系统的版本存储在保存文件中。所以称为版本的属性。

然后在最初打开文件时,您可以调用正确的方法来加载保存游戏。它可能是一个不同的方法,一个获得版本化,不同类等的接口,但是你需要为你拥有的每个保存文件版本中的一个。

在文件版本中加载后,您可以对迁移对象/方法进行编码,这些对象/方法会在内存中成为较新版本时填充默认值。与上面的检查类似,但您需要知道需要在每个版本之间设置哪些属性/值并应用默认值。这将使您能够向前迁移到每个版本的保存文件,因此可以将真正旧的保存更新为最新版本。