@TerereZero Migrations são a solução mais comum quando você quer ter um esquema mutável no banco mesmo, afaik. Pra plataforma .NET existe o
Entity Framework da microsoft, que tem
suporte embutido para migrações. Acredito que deve funcionar bem junto do Unity.
Entretanto, sobre isso:
Andei dando uma pesquisada, e realmente, usar um Banco de dados seria um exagero. Entretanto, arquivos locais não iriam satisfazer 100% a necessidade de atualizações do jogo, e no futuro a dificuldade de manutenção do projeto se tornaria um problema.
Acho que você pegou errado a ideia das migrações, e do porque elas existem para bancos de dados.
Primeiro, o banco não facilita a manutenção do modelo de dados, pelo contrário: ele estabelece várias restrições em cima do modelo, de forma que é sempre sofrível ter que mudar o esquema. Aí entram as migrações, elas são um jeito "fácil" de manter um registro das transformações feitas no modelo do banco de forma reprodutível e que garantem que o banco não explode entre uma versão do modelo e a seguinte.
Isso não quer dizer que migrations vão tornar seu trabalho mais fácil se comparado à solução simples usando serialização simples de structs, e sim que
se você precisar de um banco, e precisar mudar o modelo dele, então migrations são a solução. Se você eliminar qualquer uma das condições (i.e., não usar um banco, ou não mudar o modelo), então você não ganha nada de fato usando elas.
TL;DR: migrações de banco só existem porque é difícil mudar o esquema de um banco relacional, se você eliminar o banco não existe necessidade das migrações, porque o problema que elas resolvem deixa de existir, basicamente.
Serializando estruturas simples, você ainda consegue fazer todas as transformações que uma migration te daria. Por exemplo, supondo que começamos com um modelo assim:
C #:
[Serializable]
public class SaveData {
public uint LastUnlockedStage;
public ulong Score;
}
Seguem algumas operações que poderíamos fazer com migrations, e como faríamos usando a struct:
Adicionar um campo:
Por exemplo, vamos supor que agora existem dois conjuntos de fases, que podem ser desbloqueadas independentemente. Basta definir um campo novo com um valor default na struct:
C #:
[Serializable]
public class SaveData {
public uint LastUnlockedStage;
public ulong Score;
// Novo campo
public uint LastUnlockedSpecialStage = 0;
}
Nota: adicionar campos em tabelas existentes em migrations depende sempre de definir um valor default, caso contrário você invalida os dados da tabela.
Adicionar uma "tabela":
Com classes não temos tabelas, mas o equivalente seria uma classe nova no modelo. Por exemplo:
C #:
[Serializable]
public class SaveData {
public uint LastUnlockedStage;
public ulong Score;
// Novo campo
public uint LastUnlockedSpecialStage = 0;
// Nova classe, em um novo campo:
public InventorySaveData Inventory = default(InventorySaveData);
}
[Serializable]
public class ItemSaveData {
public uint Id;
public uint Amount;
}
[Serializable]
public class InventorySaveData {
public List<ItemSaveData> Items;
}
Remover um campo
Se por qualquer motivo você de repente quiser tirar um campo do modelo, pode simplesmente apagar ele que tudo continua funcionando:
C #:
[Serializable]
public class SaveData {
public uint LastUnlockedStage;
public ulong Score;
// Acabou o evento das fases especiais, então tiramos o campo de fase especial
public InventorySaveData Inventory = default(InventorySaveData);
}
[Serializable]
public class ItemSaveData {
public uint Id;
public uint Amount;
}
[Serializable]
public class InventorySaveData {
public List<ItemSaveData> Items;
}
Isso são alguns exemplos de transformações que você faria numa migration e que são praticamente triviais com serialização simples.
Montei um
Repl.It implementando os exemplos usando o
XmlSerializer
do C# (o código tá uma bagunça, é só uma prova de conceito mesmo haha). Usei XML ao invés de JSON porque o serializador JSON que vem embutido no .NET não funciona tão bem só com o
[Serializable]
, o XML serializa melhor as coisas automaticamente. Qualquer serialização serve, desde que se comporte bem com esse esquema.