Muitas experiências usam as estatísticas dos jogadores para acompanhar os dados da experiência do jogador no tempo. Estatísticas como pontuação alta, total de jogos vencidos, tempo total de jogo e itens coletados dão aos jogadores uma sensação de progressão e são ótimas maneiras de incentivar os jogadores a revisitar a sua experiência.
A Persistência em Verse é uma ferramenta poderosa que permite que você adicione dados persistente ao seus scripts Verse. Os dados persistentes são salvos por jogador e por ilha e permanecem os mesmos entre as sessões de jogo. Os dados persistentes permitirão que você acompanhe o progresso dos jogadores entre as sessões de jogo e proporcionarão muitas experiências de jogo interessantes e únicas anteriormente indisponíveis no UEFN.
Este tutorial mostrará como criar uma tabela personalizada de atributos de jogadores usando Verse e configurá-las para serem persistentes em vários jogos da sua experiência. Depois de concluir este tutorial, leia Faça sua própria tabela de liderança em Verse para aprender a usar a persistência para criar tabelas de liderança no jogo!
Funcionalidades da linguagem Verse usadas
Class: este exemplo cria uma classe Verse que gerencia uma única estatística, bem como uma classe persistente que acompanha um grupo de estatísticas para uma única pessoa.
Constructor: uma função especial que cria uma instância da classe com a qual está associado.
Weak_map: este é um mapa simples que não pode sofrer iteração. Os dados persistentes em Verse devem ser armazenados em um "weak_map".
Como configurar o nível
Este exemplo usa os seguintes adereços e dispositivos:
2 dispositivos Botão: quando a pessoa interage com o dispositivo, adicionará um ponto à sua pontuação atual. Você usará outro botão para simular o fim de um jogo, adicionando às vitórias ou derrotas do jogador dependendo de sua pontuação atual.
1 dispositivo Cartaz: muitas vezes, é importante exibir os dados persistentes a quem está jogando. Às vezes, isso é feito para fins de teste e, outras, para aumentar o envolvimento do jogador ou mostrar a ele seu progresso. Embora os requisitos de quando mostrar dados e quais dados exibir variem de experiência para experiência, neste exemplo, você exibirá os dados estatísticos de pontuação, maior pontuação, vitórias e derrotas em um dispositivo de cartaz.
Como rastrear atributos persistentes das pessoas
Primeiro, é importante definir quais atributos você deseja rastrear por jogador. Por exemplo, você pode querer rastrear a pontuação de todos os tempos de um jogador, sua classificação atual ou seu melhor tempo em uma volta. Neste exemplo, você rastreará a pontuação, vitórias e derrotas em uma tabela de valores de atributos para cada jogador. Você fará isso em uma nova classe, player_stats_table, que será sua classe persistente principal.
Siga estas etapas para criar sua classe player_stats_table:
Crie um novo arquivo Verse, chamado player_stats_table.verse, usando o
Explorador do Verse.Nesse novo arquivo Verse, crie uma nova classe chamada
player_stats_table. Adicione os modificadores<persistable>e<final>à sua classe. O modificador<persistable>permite que os dados na classe sejam persistentes e exige o modificador<final>, uma vez que os dados persistentes não podem ser substituídos nem é possível gerar subclasses deles.Verseusing { /Fortnite.com/Devices } using { /Verse.org/Simulation } using { /UnrealEngine.com/Temporary/Diagnostics } # Tracks different persistable stats for each player. player_stats_table := class<final><persistable>:À sua
player_stats_table, adicione três valoresintchamadosScore,WinseLosses. Eles acompanham a pontuação na duração de vida, as vitórias e as derrotas de cada jogador, respectivamente. Adicione também umintchamadoVersionpara acompanhar a versão atual da suaplayer_stats_table.Verse# Tracks different persistable stats for each player. player_stats_table := class<final><persistable>: # The version of the current stats table. Version<public>:int = 0 # The score of a player. Score<public>:int = 0 # The number of wins for a player. Wins<public>:int = 0Para criar uma instância da classe
player_stats_table, você usará uma função<constructor>. Essa função constructor é necessária porque a persistência em Verse não permite que classes contendo campos de variáveis sejam persistentes. O uso de um constructor permitirá atualizar seus valores de classe persistente criando uma cópia de uma estatística persistente existente que é variável, atualiza a cópia e substitui a instância original da classe pelos valores alterados. Adicione uma nova função de construtorMakePlayerStatsTable()ao arquivo. Este construtor usará uma instância original (anterior) da classeplayer_stats_tablee criará uma nova a partir dos valores originais fornecidos.Verse# Creates a new player_stats_table with the same values as the previous player_stats_table. MakePlayerStatsTable<constructor>(OldTable:player_stats_table)<transacts> := player_stats_table: Version := OldTable.Version Score := OldTable.Score Wins := OldTable.Wins Losses := OldTable.LossesPara acompanhar todas as
player_stats_tables, você usará umweak_mappersistente de instâncias deplayerparaplayer_stats_table. Adicione este "weak map" ao seu arquivo.Verse# Maps players to a table of their player stats. var PlayerStatsMap:weak_map(player, player_stats_table) = map{}Sua classe
player_stats_tablecompleta agora deve ficar assim:Verseusing { /Fortnite.com/Devices } using { /Verse.org/Simulation } using { /UnrealEngine.com/Temporary/Diagnostics } # Tracks different persistable stats for each player. player_stats_table := class<final><persistable>: # The version of the current stats table. Version<public>:int = 0 # The score of a player.
Como gerenciar as estatísticas de todas as pessoas
Sua classe player_stats_table permite acompanhar as estatísticas de uma pessoa individual, mas você ainda não tem como gerenciá-las. Você precisa atualizar as tabelas de atributos de cada jogador sempre que eles marcarem pontos e, dependendo do design da sua experiência, pode haver muitos jogadores ao mesmo tempo.
Para resolver isso, você usará outra classe para gerenciar as estatísticas de todos os jogadores e registrar as alterações nessas estatísticas sempre que um jogador obtiver uma vitória, derrota ou pontuação. Siga as etapas a seguir para configurar sua classe de gerenciador.
Crie um novo arquivo Verse, chamado player_stats_manager, usando o
Explorador do Verse. Nesse arquivo, crie uma nova classeplayer_stats_manager.Verseusing { /Fortnite.com/Devices } using { /Verse.org/Simulation } using { /UnrealEngine.com/Temporary/Diagnostics } # Manages and updates player_stat_tables for each player. player_stats_manager := class():Sua
player_stats_managerprecisa executar várias ações. Ela precisa configurar umaplayer_stats_tablepara uma pessoa, atualizarScore,WinseLossespor pessoa e retornarplayer_stats_tablepara uma pessoa. Você gerenciará cada uma delas em funções separadas. Adicione uma nova funçãoInitializePlayer()à definição da classeplayer_stats_manager. Essa função inicializará as estatísticas de um determinado jogador.Verse# Initialize stats for the given player. InitializePlayer(Player:player):void=Em
InitializePlayer(), verifique se a pessoa especificada já existe emPlayerStatsMap. Caso contrário, defina o valor dessa pessoa no mapa como uma novaplayer_stats_table. A funçãoInitializePlayer()completa deve ficar assim:Verse# Initialize stats for the given player. InitializePlayer(Player:player):void= if: not PlayerStatsMap[Player] set PlayerStatsMap[Player] = player_stats_table{} else: Print("Unable to initialize player stats")Adicione uma nova função
InitializeAllPlayers()à definição da classeplayer_stats_manager. Essa função usa uma matriz de pessoas e chamaInitializePlayer()em todas elas. A funçãoInitializeAllPlayers()completa deve ficar assim:Verse# Initialize stats for all current players. InitializeAllPlayers(Players:[]player):void = for (Player : Players): InitializePlayer(Player)Para retornar as estatísticas de uma pessoa específica, você precisa de uma função que retorna o
player_stats_tabledessa pessoa. Adicione uma nova funçãoGetPlayerStats()à definição da classeplayer_stats_managerque receba um agente. Adicione o modificador<decides><transacts>para permitir que essa função falhe e seja revertida no caso em que a tabela de estatísticas de uma pessoa não exista. EmGetPlayerStats(), crie uma nova variável deplayer_stats_tablechamadaPlayerStats.Verse# Return the player_stats_table for the provided Agent. GetPlayerStats(Agent:agent)<decides><transacts>:player_stats_table= var PlayerStats:player_stats_table = player_stats_table{}Em uma expressão
if, converta oagentepassado para essa função em umapessoa jogadorae, em seguida, recupere aplayer_stats_tabledessa pessoa emPlayerStatsMap. Em seguida, definaPlayerStatspara essa tabela chamandoMakePlayerStatsTable(). Por fim, retornePlayerStats. Sua funçãoGetPlayerStats()completa deve ficar assim:Verse# Return the player_stats_table for the provided Agent. GetPlayerStats(Agent:agent)<decides><transacts>:player_stats_table= var PlayerStats:player_stats_table = player_stats_table{} if: Player := player[Agent] PlayerStatsTable := PlayerStatsMap[Player] set PlayerStats = MakePlayerStatsTable(PlayerStatsTable) PlayerStatsPara atualizar cada uma das estatísticas de pontuação (Score), vitórias (Wins) e derrotas (Losses), você criará funções para cada estatística respectiva. Adicione uma nova função chamada
AddScore()ao seu arquivoplayer_stats_manager. Essa função recebe o agente para conceder pontos e a quantidade de pontos, emint, a serem concedidos.Verse# Adds to the given Agent's score and updates both their stats table # in PlayerStatsManager and the billboard in the level. AddScore<public>(Agent:agent, NewScore:int):void=Os dados são atualizados primeiramente validando se a pessoa tem os dados válidos no elemento persistente
weak_mape depois substituindo esses dados por uma cópia atualizada da classe. Para gerenciar isso para a pontuação, recupere a pontuação da pessoa dePlayerStatsTable, então defina a tabela emPlayerStatsMapcomo o resultado da construção de uma novaplayer_stats_tableusandoMakePlayerStatsTable(), passando a pontuação atual mais a nova pontuação. Quando você trabalha com uma classe que contém vários campos, o construtor da classe permite atualizar facilmente um único campo sem copiar explicitamente todos os campos sempre que quiser fazer uma atualização. Sua funçãoAddScore()deve ficar assim:Verse# Adds to the given Agent's score and updates both their stats table # in PlayerStatsManager and the billboard in the level. AddScore<public>(Agent:agent, NewScore:int):void= if: Player := player[Agent] PlayerStatsTable := PlayerStatsMap[Player] CurrentScore := PlayerStatsTable.Score set PlayerStatsMap[Player] = player_stats_table: MakePlayerStatsTable<constructor>(PlayerStatsTable) Score := CurrentScore + NewScoreRepita esse processo para vitórias e derrotas, adicionando
NewWinseNewLossesàs vitórias ou derrotas da pessoa, respectivamente, chamandoMakePlayerStatsTable().Verse# Adds to the given Agent's wins and updates both their stats table # in PlayerStatsManager and the billboard in the level. AddWin<public>(Agent:agent, NewWins:int):void= if: Player := player[Agent] PlayerStatsTable := PlayerStatsMap[Player] CurrentWins := PlayerStatsTable.Wins set PlayerStatsMap[Player] = player_stats_table: MakePlayerStatsTable<constructor>(PlayerStatsTable) Wins := CurrentWins + NewWinsO arquivo
player_stats_managerfinal deve ficar assim.Verseusing { /Fortnite.com/Devices } using { /Verse.org/Simulation } using { /UnrealEngine.com/Temporary/Diagnostics } # Manages and updates player_stat_tables for each player. player_stats_manager := class(): # Return the player_stats_table for the provided Agent. GetPlayerStats(Agent:agent)<decides><transacts>:player_stats_table= var PlayerStats:player_stats_table = player_stats_table{}
Como testar a persistência com dispositivos
Agora que você configurou suas classes de persistência, é hora de testá-las no nível.
Crie um novo dispositivo Verse chamado player_stats_example. Consulte Criar o próprio dispositivo usando Verse para conhecer as etapas.
Acima da definição da classe
player_stats_example, adicione os seguintes campos:Um
button_deviceeditável chamadoScorePointsButton. Esse botão aumenta a pontuação do jogador sempre que é ativado.Verse# Adds to the activating player's score. @editable ScorePointsButton:button_device = button_device{}Um
billboard_deviceeditável chamadoStatsBillboard. Ele exibirá a pontuação, a maior pontuação, as vitórias e as derrotas do jogador.Verse# Displays the player's Score, High Score, Wins, and Losses @editable StatsBillboard:billboard_device = billboard_device{}Um button_device editável chamado
CheckWinButton. Esse botão zera a pontuação de cada jogador e concede a ele uma vitória ou uma derrota dependendo de sua pontuação.Verse# Resets the player's score and award them a win or a loss # depending if their current score is greater than WinScore. @editable CheckWinButton:button_device = button_device{}Um
inteditável chamadoWinScore. Essa é a pontuação que as pessoas precisam alcançar para obter uma vitória após a ativação deCheckWinButton.Verse# The score players need to reach to be awarded a win after # the CheckWinButton is activated. @editable WinScore:int = 10Um
inteditável chamadoAwardScore. Essa é a pontuação que as pessoas recebem ao interagir com o botão.Verse# The amount of score to award per button press. @editable AwardScore:int = 1Um
player_stats_managerchamadoPlayerStatsManager. Ele gerenciará e atualizará as estatísticas de todos os jogadores.Verse# Manages and updates stats for each player. PlayerStatsManager:player_stats_manager = player_stats_manager{}Uma mensagem chamada `StatsMessage` que usa quatro integers: `Score`, `MaxScore`, `Wins` e `Losses`. Você usará essa mensagem para exibir os atributos de um jogador no cartaz.
Verse# Displays a player's stats on a billboard. StatsMessage<localizes>(Player:agent, Score:int, Wins:int, Losses:int):message = "{Player}, Stats:\n Score: {Score}\n Wins: {Wins}\n Losses: {Losses}"
Compile o código e arraste o dispositivo criado com Verse até a ilha. Consulte as etapas necessárias em Como adicionar seu dispositivo Verse ao seu nível.
No painel Detalhes do dispositivo, atribua o dispositivo Botão no seu nível a ScorePointsButton e atribua o dispositivo Cartaz a StatsBillboard.
Para exibir as estatísticas de uma determinada pessoa em StatsBillboard, adicione uma nova função
UpdateStatsBillboard()à definição da classeplayer_stats_example. Essa função usa o agente cujas estatísticas serão exibidas.Verse# Retrieves the stats of the given player and displays their stats # on the StatsBillboard. UpdateStatsBillboard(Agent:agent):void=Em
UpdateStatsBillboard(), obtenha as estatísticas atuais do agente fornecido chamando a funçãoGetPlayerStats[]do gerenciador de estatísticas. Em seguida, chameSetText()em StatsBillboard, passando uma novaStatsMessage(). Para criar estaStatsMessage(), obtenha Score, Wins e Losses do agente acessando-as nas estatísticas atuais do agente. Sua funçãoUpdateStatsBillboard()completa deve ficar assim:Verse# Retrieves the stats of the given player and displays their stats # on the StatsBillboard. UpdateStatsBillboard(Agent:agent):void= if: # Get the current stats of the given agent. CurrentPlayerStats := PlayerStatsManager.GetPlayerStats[Agent] then: StatsBillboard.SetText( StatsMessage( Player := Agent,Adicione uma nova função
AddScore()à definição da classeplayer_stats_example. Essa função usa um agente e adiciona a pontuação desse agente sempre que ele interage com ScorePointsButton.Verse# Adds to the given player's score and updates both their stats table # in PlayerStatsManager and the billboard in the level. AddScore(Agent:agent):void=Em
AddScore(), obtenha as estatísticas atuais do agente fornecido, bem como sua pontuação atual. Em seguida, chameAddScore()dePlayerStatsManager, passando o agente eAwardScorepara conceder a ele uma nova pontuação. Por fim, chameUpdateStatsBillboard(), passando o agente fornecido. Sua funçãoAddScore()completa deve ficar assim:Verse# Adds to the given player's score and updates both their stats table # in PlayerStatsManager and the billboard in the level. AddScore(Agent:agent):void= if: CurrentPlayerStats := PlayerStatsManager.GetPlayerStats[Agent] CurrentScore := CurrentPlayerStats.Score then: Print("Current Score is: {CurrentScore}") PlayerStatsManager.AddScore(Agent, AwardScore) UpdateStatsBillboard(Agent)Para conceder a uma pessoa uma vitória ou uma derrota quando ela interagir com o botão CheckWin, adicione uma nova função
CheckWin()à definição da classe player_stats_manager.Verse# Awards a player a win or a loss when they interact # with the CheckWinButton. CheckWin(Agent:agent):void=Primeiro, defina uma variável
CurrentScorepara acompanhar a pontuação atual do agente. Depois, como fez com a funçãoAddScore(), recupere a pontuação atual da tabela de estatísticas da pessoa.Verse# Awards a player a win or a loss when they interact # with the CheckWinButton. CheckWin(Agent:agent):void= var CurrentScore:int = 0 if: PlayerStats := PlayerStatsManager.GetPlayerStats[Agent] set CurrentScore = PlayerStats.ScoreSe a pontuação atual do agente for maior que
WinScore, você precisará registrar uma vitória emPlayerStatsManager. Caso contrário, registre uma derrota. Por fim, restaure a pontuação do agente chamandoAddScore()com umCurrentScorenegativo e, em seguida, exiba as estatísticas do agente no cartaz de estatísticas. A sua funçãoCheckWin()completa deve ficar assim:Verse# Awards a player a win or a loss when they interact # with the CheckWinButton. CheckWin(Agent:agent):void= var CurrentScore:int = 0 if: PlayerStats := PlayerStatsManager.GetPlayerStats[Agent] set CurrentScore = PlayerStats.Score then: Print("Current Score is: {CurrentScore}") if:Em
OnBegin(), inscrevaScorePointsButton.InteractedWithEventemAddScore()eCheckWinButton.InteractedWithEventemCheckWin(). Em seguida, obtenha a matriz de cada pessoa no jogo chamandoGetPlayers()e inicialize todas elas usando a funçãoInitializeAllPlayers()do gerenciador de estatísticas.Verse# Runs when the device is started in a running game OnBegin<override>()<suspends>:void= # Register Button Events ScorePointsButton.InteractedWithEvent.Subscribe(AddScore) CheckWinButton.InteractedWithEvent.Subscribe(CheckWin) Players := GetPlayspace().GetPlayers() # Initialize player stats PlayerStatsManager.InitializeAllPlayers(Players)Salve seu código e compile-o.
Como testar a persistência no seu nível
Você pode testar seus dados persistentes em uma sessão de edição, mas esses dados serão redefinidos quando você sair e reiniciar a sessão. Para que seus dados persistam entre sessões, você terá que iniciar uma sessão de teste e alterar certas configurações em Configurações da Ilha. Consulte informações sobre como configurar sua ilha para testar dados persistentes em sessões de edição e de teste em Como testar com dados persistentes na página de dados persistentes.
Depois de configurar sua sessão, quando testar seu nível, a interação com o botão ScorePoints deve aumentar a pontuação do jogador e exibir essa atualização no cartaz. A interação com o botão CheckWin deve aumentar as vitórias ou derrotas do jogador, dependendo da pontuação do jogador. Depois de retornar ao lobby e entrar novamente na sua ilha, as estatísticas do jogador deverão persistir, e seu total de vitórias/derrotas e a maior pontuação deverão ser exibidos no cartaz sempre que ele for atualizado.
Por si só
Ao concluir este guia, você terá aprendido a usar Verse para criar dados persistentes acompanhados por jogador que são mantidos entre as sessões de jogo. Agora, veja como você pode adaptar a persistência para elevar sua própria experiência.
Você consegue criar um sistema de arquivos salvos que memoriza o último ponto de verificação no qual uma pessoa chegou?
Que tal um sistema que memoriza com quais personagens você conversou e seu relacionamento atual com eles?
E um sistema que dê às pessoas apenas um tempo limitado entre as sessões para atingir metas e que redefine seu progresso se elas falharem?
Código completo
Aqui está o código completo feito no tutorial desta seção.
player_stats_table.verse
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }
# Tracks different persistable stats for each player.
player_stats_table := class<final><persistable>:
# The version of the current stats table.
Version<public>:int = 0
# The score of a player.
player_stats_manager.verse
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }
# Manages and updates player_stat_tables for each player.
player_stats_manager := class():
# Return the player_stats_table for the provided Agent.
GetPlayerStats(Agent:agent)<decides><transacts>:player_stats_table=
var PlayerStats:player_stats_table = player_stats_table{}
player_stats_example.verse
using { /Fortnite.com/Devices }
using { /Fortnite.com/Game }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }
# A Verse-authored creative device that can be placed in a level
player_stats_example := class(creative_device):
# Adds to the activating player's score.
@editable