Les données persistables vous permettent de suivre et d'enregistrer des données par joueur d'une session de jeu à l'autre. Les données persistantes reposent sur le stockage des données de chaque joueur, telles que leur profil ou leurs statistiques, dans Verse. Ces données peuvent alors être mises à jour autant de fois qu'elles sont modifiées. Ces données étant persistantes, elles resteront d'une session de jeu à l'autre et seront disponibles chaque fois que le joueur est en ligne dans le jeu. Pour plus d'informations, consultez la rubrique Utiliser des données persistables dans Verse.
Cette page aborde certaines des meilleures pratiques à adopter lorsque vous travaillez avec des données persistables dans Verse.
Utiliser des classes pour ajouter de nouveaux champs ultérieurement
Actuellement, seul le type de données persistables class est modifiable après avoir publié votre île, à condition que les nouveaux champs comportent des valeurs par défaut. Cela signifie que le chargement de données enregistrées à partir d'une version précédente inclura les nouveaux champs et leurs valeurs par défaut.
Prenons un exemple de publication d'un projet avec les données persistantes suivantes.
player_profile_data := class<final><persistable>:
Class:player_class = player_class.Villager
XP:int = 0
Rank:int = 0Le projet étant publié et en direct, ces données persistantes seront associées aux joueurs qui ont joué au jeu. Si nous ajoutions des champs aux données de profil des joueurs, comme le nombre de quêtes et l'historique, les données persistantes pourraient alors se présenter comme suit dans le projet mis à jour.
player_profile_data := class<final><persistable>:
Class:player_class = player_class.Villager
XP:int = 0
Rank:int = 0
CompletedQuestCount:int = 0
QuestHistory:[]string = array{}Les données persistantes de tous les joueurs ayant joué avec la première version de la classe player_profile_data incluront désormais les nouveaux champs :
CompletedQuestCount, avec la valeur0, qui est la valeur par défaut spécifiée.QuestHistory, avec une matrice de chaînes vide, qui est la valeur par défaut spécifiée.
Cela fonctionne parce qu'une valeur par défaut a été fournie pour les nouveaux champs afin de pouvoir mettre à jour l'ancienne version des données.
Du fait que seules les classes peuvent être mises à jour après la publication d'un projet, nous vous recommandons vivement d'utiliser une classe comme type de valeur de toute variable weak_map à étendue de module.
Pour plus d'informations sur la création d'une classe persistante, consultez la rubrique Types persistants.
Utiliser des constructeurs pour les mises à jour partielles
Si vous utilisez des classes, nous vous recommandons d'utiliser un constructeur pour créer une nouvelle instance de votre classe contenant l'état mis à jour, car les constructeurs vous permettent d'effectuer des mises à jour partielles des classes.
L'exemple suivant illustre la mise à jour du PlayerProfileDataMap. La fonction GrantXP() obtient les données actuelles du joueur concerné, puis appelle le constructeur MakePlayerProfileData() pour créer une nouvelle version de ses données de profil. Étant donné que les données sources du joueur sont transmises au constructeur avec la nouvelle valeur EXP, seule celle-ci sera modifiée tandis que toutes les autres resteront identiques.
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:
L'exemple précédent illustre la mise à jour d'un champ, mais vous pouvez en mettre à jour autant que nécessaire comme suit :
set PlayerProfileDataMap[Player] = player_profile_data:
QuestHistory := UpdatedSaveData.QuestHistory
CompletedQuestCount := OldData.CompletedQuestCount + 1
MakePlayerProfileData<constructor>(OldData)Contrôle de version des données persistables
Nous vous recommandons d'utiliser le contrôle de version dans les classes persistables pour détecter la version de l'instance des données précédemment enregistrées pour un joueur. En utilisant les versions, vous pouvez détecter et appliquer des migrations si la définition de votre classe persistante ou votre logique de gameplay change au fil du temps.
Bien que vous puissiez utiliser des valeurs entières ou de chaîne pour indiquer la version de votre classe persistante, nous vous recommandons d'utiliser des valeurs d'option pour stocker des références aux versions actuelles et passées de vos données. Prenons la configuration suivante :
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.
Ici, la classe player_data contient des valeurs d'option pour les première et deuxième versions de la classe de données associée, qui sont représentées par les classes v1_player_data et v2_player_data. Une seule des versions V1 ou V2 doit être définie pour empêcher que plusieurs versions de données soient associées aux joueurs.
Les données du joueur V1 d'origine contiennent trois champs int. La version V2 des données modifie le champ Temps de jeu en float, tout en ajoutant deux nouveaux champs. Le type du champ Temps de jeu ayant changé dans la version V2, il devra être converti pour tout joueur qui possède encore les anciennes données V1. Lorsqu'un joueur avec d'anciennes données V1 rejoint une expérience, vous pouvez utiliser des fonctions constructeur d'aide pour créer une nouvelle classe de données V2 basée sur ses anciennes données, comme suit :
# 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
Il sera parfois souhaitable de forcer une réinitialisation des données pour les joueurs rejoignant votre île. Pour ce faire, réattribuez une valeur par défaut aux données persistables dans le "weak_map" pour tous les joueurs et modifiez le champ Version de la classe. Si vous utilisez des données versionnées facultatives, vous pouvez réinitialiser les données en définissant les champs facultatifs sur false.
Pour savoir si les données des joueurs ont déjà été réinitialisées, vous pouvez consulter la valeur Version dans les données persistables des joueurs, pour vérifier s'il s'agit de la dernière.
S'assurer du respect des limites
Si votre mise à jour peut influer sur la taille totale des données persistantes, vérifiez que ces dernières respectent toujours les contraintes du système de persistance de Verse. Si vous tentez de mettre à jour les données persistantes et que vous dépassez la taille limite, vous recevez une erreur d'exécution Verse. Consultez la rubrique Taille maximale des objets persistants pour plus d'informations.
Vous pouvez vérifier comment vos mises à jour influent sur la taille totale à l'aide de la fonction FitsInPlayerMap().
Dans l'exemple suivant, les données persistantes contiennent une matrice de chaînes. Si cette matrice devient trop grande pour être stockée dans le weak_map, ce qui se produit lorsque FitsInPlayerMap() échoue, l'exemple vide la matrice et ajoute uniquement le dernier élément enregistré.
# 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]
Réagir à l'arrivée d'un joueur sur votre île
Lorsqu'un nouveau joueur rejoint votre île, aucune entrée n'est automatiquement ajoutée au weak_map persistable. Vous devrez ajouter cette entrée dans Verse.
Pour cela, vous pouvez vérifier si un joueur est déjà dans le weak_map chaque fois que vous y accédez ou ajouter des données par défaut au weak_map chaque fois qu'un joueur le rejoint, ce que vous pouvez savoir en vous abonnant à l'événement PlayerAddedEvent() du jeu.
GetPlayspace().PlayerAddedEvent().Subscribe(OnPlayerAdded)
# Later in your file
OnPlayerAdded(Player:player):void=
if:
not PlayerProfileDataMap[Player]
set PlayerProfileDataMap[Player] = player_profile_data{}