De nombreux jeux utilisent les statistiques des joueurs pour suivre l'évolution des joueurs au fil du temps. Des statistiques telles que le meilleur score, le nombre total de parties gagnées, le temps de jeu total et les objets collectés donnent aux joueurs un sentiment de progression et sont autant de moyens de les encourager à revenir jouer à vos jeux.
La persistance Verse est un puissant outil qui vous permet d'ajouter des données persistantes à vos scripts Verse. Les données persistantes sont enregistrées par joueur et par île et restent inchangées entre les sessions de jeu. Elles vous permettent de suivre la progression des joueurs et donnent accès à diverses expériences de jeu originales et intéressantes qui n'étaient pas disponibles auparavant dans l'UEFN.
Dans ce tutoriel, nous vous expliquons comment créer un tableau personnalisé de statistiques de joueur avec Verse et comment le configurer pour qu'il soit conservé d'une session de jeu à l'autre. Au terme de ce tutoriel, consultez la rubrique Créer votre propre classement dans le jeu avec Verse pour apprendre à utiliser la persistance et créer des classements de jeu intégrés.
Fonctionnalités du langage Verse utilisées
Classe : dans cet exemple, nous allons créer une classe Verse qui gère une seule statistique ainsi qu'une classe persistante qui suit un groupe de statistiques d'un joueur unique.
Constructeur : un constructeur est une fonction spéciale qui crée une instance de la classe à laquelle il est associé.
Mappage faible : un mappage faible est un mappage simple qui ne peut pas être itéré. Les données persistantes Verse doivent être stockées dans un mappage_faible.
Configurer le niveau
Dans cet exemple, nous utiliserons les accessoires et appareils suivants.
2 boutons : lorsque le joueur interagit avec l'appareil, un point est ajouté à son score actuel. Vous utiliserez un autre appareil Bouton pour simuler la fin d'une partie, en ajoutant les victoires ou les défaites du joueur en fonction de son score.
1 panneau d'affichage : il est souvent important d'afficher des données persistantes à l'intention du joueur. Parfois à des fins de test, parfois pour stimuler son engagement ou lui montrer les progrès accomplis. Bien que les exigences relatives au moment de l'affichage des données et aux données à afficher varient d'une expérience à l'autre, dans cet exemple, vous allez afficher les données de statistiques pour le score, le meilleur score, les victoires et les défaites sur un panneau d'affichage.
Effectuer le suivi des statistiques de joueur persistantes
Tout d'abord, il est important de définir les statistiques que vous souhaitez suivre par joueur. Par exemple, vous souhaiterez peut-être suivre le score de tous les temps effectués par un joueur, son classement actuel ou ses meilleurs temps au tour. Dans cet exemple, vous allez suivre les scores, les victoires et les défaites dans un tableau de valeurs de statistiques pour chaque joueur. Vous allez pour cela utiliser une nouvelle classe, player_stats_table, qui sera votre classe persistante principale.
Procédez comme suit pour créer votre classe player_stats_table :
Créez un nouveau fichier Verse à l'aide de l'explorateur Verse nommé
player_stats_table.verse.Dans votre nouveau fichier Verse, créez une nouvelle classe nommée
player_stats_table. Ajoutez les modificateurs<persistable>et<final>à votre classe. Le modificateur<persistable>permet de rendre persistantes les données de la classe et doit disposer du modificateur<final>, car les données persistantes ne peuvent être ni remplacées ni utilisées comme parentes d'une sous-classe.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>:À votre
player_stats_table, ajoutez trois valeursintnomméesScore,WinsetLosses. Elles permettent de suivre le score, les victoires et les défaites de chaque joueur depuis sa première participation au jeu. Ajoutez également une valeurintnomméeVersionpour suivre la version actuelle de votreplayer_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 = 0Pour créer une instance de la
classe player_stats_table, vous allez utiliser une fonction<constructor>. Ce constructeur est nécessaire, car la persistance Verse n'autorise pas la persistance des classes contenant des champs de variables. L'utilisation d'un constructeur vous permet de mettre à jour les valeurs de votre classe persistante en créant une copie d'une statistique persistante existante qui est une variable, en mettant à jour la copie, puis en remplaçant l'instance d'origine de la classe par les valeurs modifiées. Ajoutez une nouvelle fonction de constructeurMakePlayerStatsTable()à votre fichier. Ce constructeur prend une instance d'origine (précédente) de la classeplayer_stats_tableet en crée une nouvelle à partir des valeurs d'origine données.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.LossesPour suivre toutes vos classes
player_stats_table, vous allez utiliser un autreweak_mappersistant deplayervers les instances deplayer_stats_table. Ajoutez cette variable `weak_map` à votre fichier.Verse# Maps players to a table of their player stats. var PlayerStatsMap:weak_map(player, player_stats_table) = map{}Votre classe
player_stats_tablecomplète doit maintenant ressembler à ceci :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.
Gérer les statistiques de tous les joueurs
Votre classe player_stats_table vous permet de suivre les statistiques d'un joueur, mais pas encore de les gérer. Vous devez mettre à jour les tableaux de statistiques de chaque joueur chaque fois qu'il marque des points et, selon la conception de votre expérience, il peut y avoir plusieurs joueurs à gérer.
Pour résoudre ce problème, vous utiliserez une autre classe pour gérer les statistiques de tous les joueurs et enregistrer les changements de statistiques lorsqu'un joueur gagne, perd ou marque un point. Procédez comme suit pour configurer votre classe de gestionnaire.
À l'aide de l'explorateur Verse, créez un nouveau fichier Verse nommé
player_stats_manager. Dans ce fichier, créez une nouvelle 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():Votre classe
player_stats_managera plusieurs tâches à accomplir. Elle doit configurer une classeplayer_stats_tablepar joueur, mettre à jour les valeursScore,WinsetLossesde chaque joueur, puis renvoyer la classeplayer_stats_tabled'un joueur. Chacune de ces missions sera gérée dans une fonction distincte. Ajoutez une nouvelle fonctionInitializePlayer()à la définition de votre classeplayer_stats_manager. Cette fonction permet d'initialiser les statistiques d'un joueur donné.Verse# Initialize stats for the given player. InitializePlayer(Player:player):void=Dans
InitializePlayer(), vérifiez si le joueur donné existe déjà dans lePlayerStatsMap. Si ce n'est pas le cas, la valeur de ce joueur dans le mappage est placée dans un nouveauplayer_stats_table. Votre fonctionInitializePlayer()achevée doit ressembler à ce qui suit :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")Ajoutez une nouvelle fonction
InitializeAllPlayers()à la définition de votre classeplayer_stats_manager. Cette fonction prend une matrice de joueurs et appelleInitializePlayer()sur chacun d'eux. Votre fonctionInitializeAllPlayers()achevée doit ressembler à ce qui suit :Verse# Initialize stats for all current players. InitializeAllPlayers(Players:[]player):void = for (Player : Players): InitializePlayer(Player)Pour obtenir les statistiques d'un joueur particulier, vous devez disposer d'une fonction qui renvoie le
player_stats_tablede ce joueur. Ajoutez une nouvelle fonctionGetPlayerStats()à la définition de classeplayer_stats_managerqui prend un agent. Ajoutez le modificateur<decides><transacts>pour permettre à cette fonction d'échouer et de s'annuler en l'absence de tableau de statistiques d'un joueur. DansGetPlayerStats(), créez une nouvelle variablePlayerStatsduplayer_stats_table.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{}Dans une expression
if, convertissez l'agenttransmis à cette fonction en unjoueur, puis récupérez leplayer_stats_tablede ce joueur à partir dePlayerStatsMap. Attribuez ensuitePlayerStatsà ce tableau en appelantMakePlayerStatsTable(). Enfin, renvoyezPlayerStats. Votre fonctionGetPlayerStats()complète doit ressembler à ce qui suit :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) PlayerStatsPour mettre à jour chacune des statistiques de score, de victoires et de défaites, vous allez créer des fonctions pour chaque statistique. Ajoutez une nouvelle fonction nommée
AddScore()à votre fichierplayer_stats_manager. Cette fonction capture l'agent à qui attribuer un score et le nombre de pointsintà lui attribuer.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=Les données sont mises à jour en confirmant d'abord que le joueur possède des données valides dans le mappage persistant
weak_map, puis en remplaçant ces données par une copie mise à jour de la classe. Pour gérer cela dans le cas du score, récupérez le score du joueur dans le tableauPlayerStatsTable, puis définissez le tableau dans lePlayerStatsMapcomme le résultat de la construction d'un nouveauplayer_stats_tableen utilisantMakePlayerStatsTable(), puis en transmettant le score actuel et le nouveau score. Lorsque vous travaillez avec une classe qui contient plusieurs champs, le constructeur de classe vous permet de mettre à jour facilement un seul champ sans avoir à copier explicitement tous les champs chaque fois que vous souhaitez effectuer une mise à jour. Votre fonctionAddScore()doit ressembler à ce qui suit :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 + NewScoreRépétez cette procédure pour les victoires et les défaites, en ajoutant
NewWinsetNewLossesaux victoires ou aux défaites du joueur, respectivement, lors de l'appel deMakePlayerStatsTable().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 + NewWinsVotre fichier
player_stats_managerfinal doit ressembler à ce qui suit.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{}
Tester la persistance avec des appareils
Maintenant que vous avez configuré vos classes de persistance, il est temps de les tester dans votre niveau.
Créez un nouvel appareil Verse nommé player_stats_example. Consultez la page Créer votre propre appareil avec Verse pour connaître la procédure.
En haut de la définition de la classe
player_stats_example, ajoutez les champs suivants :Un appareil
button_devicemodifiable nomméScorePointsButton. Ce bouton incrémente le score du joueur chaque fois qu'il est activé.Verse# Adds to the activating player's score. @editable ScorePointsButton:button_device = button_device{}Un appareil
billboard_devicemodifiable nomméStatsBillboard. Il affiche le score, le meilleur score, les victoires et les défaites du joueur.Verse# Displays the player's Score, High Score, Wins, and Losses @editable StatsBillboard:billboard_device = billboard_device{}Un appareil button_device modifiable nommé
CheckWinButton. Ce bouton réinitialise le score de chaque joueur et lui attribue une victoire ou une défaite en fonction du score de son joueur.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{}Un
intmodifiable nomméWinScore. Il s'agit du score que les joueurs doivent obtenir pour se voir attribuer une victoire après l'activation duCheckWinButton.Verse# The score players need to reach to be awarded a win after # the CheckWinButton is activated. @editable WinScore:int = 10Un
intmodifiable nomméAwardScore. Il s'agit du score attribué aux joueurs lorsqu'ils interagissent avec le bouton.Verse# The amount of score to award per button press. @editable AwardScore:int = 1Un
player_stats_managernomméPlayerStatsManager. Cette fonction permet de gérer et de mettre à jour les statistiques de tous les joueurs.Verse# Manages and updates stats for each player. PlayerStatsManager:player_stats_manager = player_stats_manager{}Un message nommé StatsMessage qui prend un agent avec quatre nombres entiers : Score, MaxScore, Wins et Losses. Vous utiliserez ce message pour afficher les statistiques d'un joueur sur le panneau d'affichage.
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}"
Compilez votre code et faites glisser l'appareil créé avec Verse sur votre île. Consultez la page Ajouter votre appareil Verse à votre niveau pour connaître la procédure.
Dans le panneau Détails de votre appareil, attribuez le bouton de votre niveau à ScorePointsButton et le panneau d'affichage à StatsBillboard.
Pour afficher les statistiques d'un joueur donné sur le StatsBillboard, ajoutez une fonction
UpdateStatsBillboard()à la définition de votre classeplayer_stats_example. Cette fonction prend l'agent dont les statistiques doivent être affichées.Verse# Retrieves the stats of the given player and displays their stats # on the StatsBillboard. UpdateStatsBillboard(Agent:agent):void=Dans
UpdateStatsBillboard(), obtenez les statistiques actuelles de l'agent donné en appelant la fonctionGetPlayerStats[]du gestionnaire de statistiques. Ensuite, appelezSetText()sur le StatsBillboard en transmettant un nouveauStatsMessage(). Pour construire ceStatsMessage(), obtenez le score, les victoires et les défaites de l'agent en y accédant à partir des statistiques actuelles de l'agent. Votre fonctionUpdateStatsBillboard()achevée doit ressembler à ce qui suit :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,Ajoutez une nouvelle fonction
AddScore()à la définition de votre classeplayer_stats_example. Cette fonction prend un agent et incrémente son score chaque fois qu'il interagit avec le 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=Dans
AddScore(), récupérez les statistiques et le score actuel de l'agent donné. Appelez ensuiteAddScore()depuis lePlayerStatsManager, en transmettant l'agent et leAwardScorepour lui attribuer un nouveau score. Enfin, appelezUpdateStatsBillboard()en transmettant l'agent donné. Votre fonctionAddScore()achevée doit ressembler à ce qui suit :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)Pour attribuer une victoire ou une défaite à un joueur lorsque le bouton CheckWin fait l'objet d'une interaction, ajoutez une nouvelle fonction
CheckWin()à la définition de la classe player_stats_manager.Verse# Awards a player a win or a loss when they interact # with the CheckWinButton. CheckWin(Agent:agent):void=Commencez par définir une variable
CurrentScorepour suivre le score actuel de l'agent. Ensuite, comme avec la fonctionAddScore(), récupérez son score actuel dans son tableau de statistiques de joueur.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.ScoreSi le score actuel de l'agent est supérieur à la valeur de
WinScore, vous devez enregistrer une victoire dans lePlayerStatsManager. Sinon, enregistrez une défaite. Enfin, réinitialisez le score de l'agent en appelantAddScore()avec unCurrentScorenégatif, puis affichez les statistiques de l'agent sur le panneau d'affichage des statistiques. Votre fonctionCheckWin()achevée doit ressembler à ce qui suit :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:Dans
OnBegin(), abonnezScorePointsButton.InteractedWithEventàAddScore()etCheckWinButton.InteractedWithEventàCheckWin(). Récupérez ensuite la matrice de chaque joueur dans le jeu en appelantGetPlayers(), puis initialisez-les toutes à l'aide de la fonctionInitializeAllPlayers()du gestionnaire de statistiques.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)Enregistrez votre code et compilez-le.
Tester la persistance dans le niveau
Vous pouvez tester vos données persistantes dans une session de modification, mais ces données seront réinitialisées lorsque vous quitterez la session et la relancerez. Pour conserver vos données d'une session à l'autre, vous devez lancer une session de test de jeu et modifier certains paramètres de l'île. Pour en savoir plus sur la configuration de votre île afin de tester les données persistantes dans les sessions de modification et dans les sessions de test, consultez la rubrique Tester avec des données persistantes sur la page des données persistantes.
Après avoir configuré votre session, lorsque vous testez votre niveau, l'interaction avec le bouton ScorePoints devrait incrémenter le score du joueur et afficher cette mise à jour sur le panneau d'affichage. L'interaction avec le bouton CheckWin devrait incrémenter les victoires ou les défaites du joueur en fonction de son score. Une fois le joueur revenu dans le salon et sur votre île rouverte, ses statistiques doivent persister et son total de victoires/défaites s'afficher sur le panneau d'affichage chaque fois qu'il évolue, tout comme son meilleur score.
À vous de jouer
Au cours de ce tutoriel, vous avez appris à utiliser Verse pour créer des données persistantes par joueur qui subsistent d'une session de jeu à l'autre. Découvrez maintenant comment adapter la persistance pour améliorer votre propre expérience.
Pouvez-vous créer un système de fichiers d'enregistrement qui mémorise le dernier point de contrôle qu'un joueur a atteint ?
Que diriez-vous d'un système qui conserve en mémoire les personnages auxquels vous avez parlé et votre relation avec eux ?
Et si vous construisiez un système qui n'accorde aux joueurs qu'un temps limité pour atteindre leurs objectifs et qui réinitialise leur progression s'ils échouent ?
Code complet
Voici le code complet généré dans cette section :
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