Dados persistentes permitem rastrear e salvar dados por jogador entre sessões de jogo. Os dados persistentes funcionam armazenando dados de cada jogador individual, como perfil ou estatísticas, no Verse. Esses dados podem então ser atualizados quantas vezes o valor dos dados mudar. Como são persistentes, eles persistirão durante as sessões de jogo e estarão disponíveis sempre que o jogador estiver on-line no jogo. Para obter mais informações, consulte Como usar dados persistentes em Verse.
Essa página aborda algumas práticas recomendadas ao trabalhar com dados persistentes no Verse.
Use classes para adicionar novos campos posteriormente.
Atualmente, o único tipo de dados persistentes que você pode alterar após publicar sua Ilha é o class, desde que novos campos tenham valores padrão. Isso significa que o carregamento dos dados salvos de uma versão anterior incluirá os novos campos e seus valores padrão.
Vejamos um exemplo de publicação de um projeto com os seguintes dados persistentes.
player_profile_data := class<final><persistable>:
Class:player_class = player_class.Villager
XP:int = 0
Rank:int = 0Como o projeto foi publicado e está ativo, os jogadores que jogaram o jogo terão esses dados persistentes associados a eles. Se adicionarmos mais campos aos dados do perfil do jogador, como contagem de missões e histórico, os dados persistentes poderiam ter a seguinte aparência no projeto atualizado.
player_profile_data := class<final><persistable>:
Class:player_class = player_class.Villager
XP:int = 0
Rank:int = 0
CompletedQuestCount:int = 0
QuestHistory:[]string = array{}Os dados persistentes de qualquer jogador que jogou com a primeira versão da classe player_profile_data incluirão agora os novos campos:
CompletedQuestCountcom o valor de0, que é o valor padrão especificado.QuestHistorycom uma matriz de string vazia, que é o valor padrão especificado.
Isso funciona porque um valor padrão foi fornecido para os novos campos para poder atualizar a versão mais antiga dos dados.
Como apenas as classes podem ser atualizadas após a publicação de um projeto, recomendamos o uso de uma classe como o tipo de valor de qualquer variável weak_map com escopo de módulo.
Consulte mais detalhes sobre como criar uma classe persistente em Tipos persistentes.
Como usar construtores para atualizações parciais
Se você estiver usando classes, recomendamos usar um constructor para criar uma nova instância da sua classe que contenha o estado atualizado, já que construtores permitem fazer atualizações parciais de classes.
O exemplo a seguir mostra como você pode atualizar PlayerProfileDataMap. A função GrantXP() obtém os dados atuais de um determinado jogador e aciona o construtor MakePlayerProfileData() para criar uma nova versão dos seus dados de perfil. Como os dados de origem do jogador são passados para o construtor junto com o novo valor de EXP, apenas o valor de EXP será atualizado, enquanto todos os outros dados do jogador permanecerão inalterados.
MakePlayerProfileData<constructor>(Src:player_profile_data)<transacts> := player_profile_data:
Version := Src.Version
Class := Src.Class
XP := Src.XP
Rank := Src.Rank
CompletedQuestCount := Src.CompletedQuestCount
QuestHistory := Src.QuestHistory
GrantXP(Agent:agent, GrantedXP:int):void=
if:
O exemplo anterior mostrou como atualizar um campo, mas você pode atualizar quantos forem necessários, desta maneira:
set PlayerProfileDataMap[Player] = player_profile_data:
QuestHistory := UpdatedSaveData.QuestHistory
CompletedQuestCount := OldData.CompletedQuestCount + 1
MakePlayerProfileData<constructor>(OldData)Controle de versão de dados persistentes
Recomendamos usar o controle de versão em classes persistentes para detectar a versão da instância para dados salvos anteriormente para um jogador. Ao usar versões, você pode detectar e aplicar migrações se sua definição de classe persistente ou lógica de jogo mudar ao longo do tempo.
Embora você possa usar valores inteiros ou de string para denotar a versão da sua classe persistente, recomendamos o uso de valores de opção para armazenar referências às versões atual e anterior dos seus dados. Considere a seguinte configuração:
var SavedPlayerData:weak_map(player, player_data) = map{}
# A player data class containing optional fields of versioned player data. Only one of these
# optional values should contain a real value at any given time.
player_data := class<final><persistable>:
V1:?v1_player_data = false
V2:?v2_player_data = false
# Original version of player data.
Aqui, a classe player_data contém valores de opções para a primeira e a segunda versão da classe de dados associada, que são representadas pelas classes v1_player_data e v2_player_data. Apenas V1 ou V2 deve ser definido para evitar que os jogadores tenham várias versões de dados associadas a eles.
Os dados originais do jogador V1 contêm três campos int. A versão V2 dos dados altera o campo Tempo de reprodução para um float, além de adicionar dois novos campos. Como o tipo do campo Tempo de jogo mudou na versão V2, ele precisará ser convertido para qualquer jogador que ainda tenha os dados V1 antigos. Quando um jogador com dados V1 antigos entra em uma experiência, você pode usar as funções constructor auxiliares para criar uma nova classe de dados V2 com base em seus dados antigos, da seguinte maneira:
# Create v1_player_data using existing v1_player_data.
MakeV1PlayerData<constructor>(SourceData:v1_player_data)<transacts> := v1_player_data:
XP := SourceData.XP
Rank := SourceData.Rank
Playtime := SourceData.Playtime
# Create v2_player_data using existing v2_player_data.
MakeV2PlayerData<constructor>(SourceData:v2_player_data)<transacts> := v2_player_data:
XP := SourceData.XP
Rank := SourceData.Rank
Pode haver momentos em que você quer forçar uma redefinição de dados para jogadores que ingressam na sua ilha. Isso pode ser feito reatribuindo um valor padrão para os dados persistentes no "weak_map" para todos os jogadores e alterando o campo Version da classe. Se você usar dados com versão opcionais, poderá restaurar os dados definindo os campos opcionais como false.
Para saber se os dados do jogador já foram redefinidos, você pode verificar o valor de Version nos dados persistentes do jogador para ver se são os mais recentes.
Como testar se os dados persistentes estão dentro dos limites
Se a sua atualização puder afetar o tamanho total dos dados persistentes, você deverá verificar se os dados persistentes ainda se enquadram nas restrições do sistema de persistência em Verse. Se tentar atualizar os dados persistentes e eles excederem os limites de tamanho, você receberá um erro de tempo de execução em Verse. Consulte mais detalhes em Tamanho máximo de objetos persistentes.
Você pode verificar como suas atualizações afetam o tamanho total usando a função FitsInPlayerMap().
No exemplo a seguir, os dados persistentes contêm uma matriz de strings. Se essa matriz ficar muito grande para ser armazenada em weak_map, o que acontece quando FitsInPlayerMap() falha, o exemplo esvaziará a matriz e adicionará apenas o elemento salvo mais recentemente.
# Construct and return a new player_profile_data with updated quest history.
SetQuestHistory(Src:player_profile_data, NewQuestHistory:[]string)<transacts>:player_profile_data =
NewData:player_profile_data = player_profile_data:
MakePlayerProfileData<constructor>(Src)
QuestHistory := NewQuestHistory
# Set a player's quest history in the PlayerProfileDataMap.
RecordQuestHistory(Agent:agent, QuestHistory:string):void=
if:
CheckSaveDataForPlayer[Agent]
Como reagir a um jogador que estiver entrando na sua Ilha
Quando um novo jogador entrar na sua Ilha, ele não terá uma entrada adicionada automaticamente a weak_map persistente. Você terá que adicionar essa entrada em Verse.
Para isso, você pode verificar se um jogador já está em weak_map sempre que acessá-lo ou pode adicionar dados padrão ao weak_map sempre que um jogador entrar, o que você pode saber inscrevendo-se no evento PlayerAddedEvent() do jogo.
GetPlayspace().PlayerAddedEvent().Subscribe(OnPlayerAdded)
# Later in your file
OnPlayerAdded(Player:player):void=
if:
not PlayerProfileDataMap[Player]
set PlayerProfileDataMap[Player] = player_profile_data{}