Introdução
Cada jogo possui dados com os quais os designers de jogos trabalham. No RPG, esse é um banco de dados de itens, em match-3 - o custo em cristais de ferramentas da loja, em jogos de ação - a quantidade de HP que o kit de primeiros socorros cura.
Existem muitas maneiras de armazenar esses dados - alguém os armazena em tabelas, em arquivos xml ou json, que edita com suas próprias ferramentas. O Unity oferece seu próprio caminho - Scriptable Objects (SO), do qual gosto porque você não precisa escrever seu próprio editor para sua apresentação visual, é fácil vincular os recursos do jogo e uns aos outros e, com o advento dos endereçáveis, esses dados podem ser fácil e convenientemente armazenados fora jogos e atualização separadamente.
Neste artigo, gostaria de falar sobre minha biblioteca SODatabase, com a qual você pode criar, editar e usar convenientemente no jogo (editar e serializar) objetos de script.
Criação e edição de SO
Eu crio e edito SOs em uma janela separada, que é um pouco semelhante às janelas do projeto com um inspetor - à esquerda há uma árvore de pastas (a pasta na qual todos os SOs estão localizados - um grupo em endereçáveis) e à direita está o inspetor do SO selecionado.
Para desenhar esse WindowEditor, uso a biblioteca Odin Inspector . Além disso, eu uso a serialização para SO desta biblioteca - ela estende muito a serialização unitium padrão, permitindo que classes polimórficas, aninhamento profundo e referências de classe sejam armazenados.
Novos SOs são criados clicando em um botão nesta janela - lá você precisa selecionar o tipo de bipé desejado, e ele é criado na pasta. Para que o tipo de SO apareça nesta janela como uma opção, o SO deve herdar de DataNode, que tem apenas um campo adicional para ScriptableObject
public string FullPath { get; }
SO, .
SO
- , , SO - , — , , SO.
static SODatabase , , .
public static T GetModel<T>(string path) where T : DataNode
public static List<T> GetModels<T>(string path, bool includeSubFolders = false) where T : DataNode
, SODatabase , Addressables.
ScriptableObject , . ScriptableObject . , SO .
— , , - , . , SO . , unity, xml .
, ScriptableObject JSON.
DataNode — SO, SODatabase,
[JsonObject(MemberSerialization.OptIn, IsReference = true)]
JsonProperty save.txt . SODatabase addressables JsonConvert.PopulateObject SODatabase, .
, , SO ( , JsonProperty) -, SO . — . , , , .
-
async void Awake()
{
await SODatabase.InitAsync(null, null);
await SODatabase.LoadAsync();
}
private void OnApplicationPause(bool pauseStatus)
{
if (pauseStatus)
SODatabase.Save();
}
private void OnApplicationQuit()
{
SODatabase.Save();
}
PlayerSO, — , , . - , SODatabase, .
public class PlayerSO : DataNode
{
public static string Path => "PlayerInfo/Player";
[JsonProperty]
public string Title = string.Empty;
[JsonProperty]
public int Experience;
}
PlayerInventorySO, ( SO SODatabase).
public class PlayerInventorySO : DataNode
{
public static string Path => "PlayerInfo/PlayerInventory";
[JsonProperty]
public List<ItemSO> Items = new List<ItemSO>();
}
, — , . , , QuestSO (, , ..) . - .
public class QuestNode : BaseNode
{
public static string Path = "QuestNodes";
//Editor
public virtual string Title { get; } = string.Empty;
public virtual string Description { get; } = string.Empty;
public int TargetCount;
//Runtime
[JsonProperty]
private bool finished;
public bool Finished
{
get => finished;
set => finished = value;
}
}
, JsonProperty , SO .
var playerSO = SODatabase.GetModel<PlayerSO>(PlayerSO.Path);
var playerInventorySO = SODatabase.GetModel<PlayerInventorySO>(PlayerInventorySO.Path);
var questNodes = SODatabase.GetModels<QuestNode>(QuestNode.Path, true);
— - / , , SO, json. - , ( ..) . SO , SODatabase , Addressables.
A biblioteca está disponível publicamente no github . Escrito usando Nullable de c # 8, portanto, requer Unity 2020.1.4 como uma versão mínima.