Los datos persistentes te permiten realizar un seguimiento y guardar datos por jugador entre las sesiones de juego. Los datos persistentes funcionan mediante el almacenamiento de datos, como perfiles o estadísticas para cada jugador individual, en Verse. Estos datos después se pueden actualizar tantas veces como cambie su valor. Dado que estos datos son persistentes, permanecerán en todas las sesiones de juego y estarán disponibles en todo momento mientras el jugador esté en línea en el juego. Para obtener más información, consulta Cómo usar datos persistentes en Verse.
En esta página, se describen algunas prácticas recomendadas para trabajar con datos persistentes en Verse.
Cómo usar clases para agregar nuevos campos más tarde
Actualmente, el único tipo de datos persistentes que puedes cambiar después de publicar tu isla es el tipo de clase, siempre que los campos nuevos tengan valores predeterminados. Esto significa que al cargar los datos guardados de una versión anterior se incluirán los campos nuevos y sus valores predeterminados.
Observemos un ejemplo de publicación de un proyecto con los siguientes datos persistentes.
player_profile_data := class<final><persistable>:
Class:player_class = player_class.Villager
XP:int = 0
Rank:int = 0Como el proyecto está publicado y en vivo, los jugadores que hayan jugado el juego tendrán estos datos persistentes asociados. Si agregáramos más campos a los datos de perfil del jugador, como el historial y el recuento de misiones, los datos persistentes podrían verse de la siguiente forma en el proyecto actualizado.
player_profile_data := class<final><persistable>:
Class:player_class = player_class.Villager
XP:int = 0
Rank:int = 0
CompletedQuestCount:int = 0
QuestHistory:[]string = array{}Los datos persistentes de todos los jugadores que jugaron con la primera versión de la clase player_profile_data ahora incluirán los siguientes campos:
CompletedQuestCountcon el valor0, que es el valor predeterminado que se especificó.QuestHistorycon una matriz de cadenas vacía, que es el valor predeterminado que se especificó.
Esto funciona porque se proporcionó un valor predeterminado para los campos nuevos a fin de actualizar la versión anterior de los datos.
Como solo se pueden actualizar las clases después de que se publica un proyecto, recomendamos encarecidamente usar una clase como el tipo de valor de cualquier variable weak_map dentro del ámbito del módulo.
Para obtener más detalles sobre cómo crear una clase persistente, consulta Tipos persistentes.
Cómo usar constructores para actualizaciones parciales
Si usas clases, recomendamos usar un constructor para crear una nueva instancia de tu clase que contenga el estado actualizado, porque los constructores te permiten hacer actualizaciones parciales de las clases.
En el siguiente ejemplo, se muestra cómo puedes actualizar PlayerProfileDataMap. La función GrantXP() obtiene los datos actuales del jugador dado y, luego, llama al constructor MakePlayerProfileData() para hacer una versión nueva de sus datos de perfil. Debido a que los datos de origen del jugador se transfieren al constructor junto con el valor de PE nuevo, solo se actualizará el valor de PE y todos los demás datos del jugador seguirán siendo los mismos.
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:
En el ejemplo anterior, se mostró cómo actualizar un solo campo, pero puedes actualizar todos los campos que necesites de la siguiente manera:
set PlayerProfileDataMap[Player] = player_profile_data:
QuestHistory := UpdatedSaveData.QuestHistory
CompletedQuestCount := OldData.CompletedQuestCount + 1
MakePlayerProfileData<constructor>(OldData)Control de versiones de datos persistentes
Recomendamos utilizar el control de versiones en las clases persistentes para detectar la versión de la instancia de los datos que se guardaron anteriormente para un jugador. Al usar las versiones, puedes detectar y aplicar migraciones si la definición de la clase persistente o la lógica de jugabilidad cambian con el tiempo.
Si bien puedes usar valores enteros o de cadena para indicar la versión de tu clase persistente, recomendamos usar valores de opción para almacenar referencias a versiones actuales y pasadas de tus datos. Veamos la siguiente configuración:
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.
Aquí, la clase player_data contiene valores de opción tanto para la primera como para la segunda versión de la clase asociada de datos, que están representadas por las clases v1_player_data y v2_player_data. Solo se debe establecer una de V1 o V2 para evitar que los jugadores tengan múltiples versiones asociadas de datos.
Los datos del jugador de V1 originales contienen tres campos int. La versión V2 de los datos cambia el campo tiempo de juego a un float, además de añadir dos nuevos campos. Debido a que el tipo del campo tiempo de juego cambió en la versión V2, tendrá que convertirse para cualquier jugador que todavía tenga los datos antiguos de V1. Cuando un jugador con datos antiguos de V1 se une a una experiencia, puedes usar las funciones de constructor de ayudante para compilar una nueva clase de datos V2 basada en sus datos antiguos, de la siguiente manera:
# 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
Es posible que a veces desees forzar un restablecimiento de los datos para los jugadores que se unen a tu isla. Para llevar esto a cabo, reasigna un valor predeterminado de los datos persistentes en el 'weak_map' para todos los jugadores y cambia el campo versión de la clase. Si usas datos versionados opcionales, puedes restablecer los datos al establecer los campos opcionales en falso.
Para saber si ya se restablecieron los datos del jugador, puedes comprobar el valor de versión en los datos persistentes del jugador a fin de comprobar si se trata de la versión más reciente.
La prueba de que los datos persistentes están dentro de los límites
Si tu actualización puede afectar al tamaño total de los datos persistentes, debes verificar que estos datos todavía estén dentro de las restricciones del sistema de persistencia de Verse. Si intentas actualizar los datos persistentes y excedes los límites de tamaño, recibirás un error en tiempo de ejecución de Verse. Consulta Tamaño máximo de objetos persistentes para obtener más detalles.
Puedes revisar cómo influyen las actualizaciones en el tamaño total. Para ello, utiliza la función FitsInPlayerMap().
En el siguiente ejemplo, los datos persistentes contienen una matriz de cadenas de caracteres. Si esa matriz alguna vez se vuelve demasiado grande para almacenarla en el weak_map, lo que sucede cuando FitsInPlayerMap() falla, el ejemplo vacía la matriz y solo añade el elemento guardado más reciente.
# 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]
Cómo reaccionar frente a un jugador que se une a la isla
Cuando un nuevo jugador se una a tu isla, no se le añadirá una entrada de forma automática al weak_map persistente. Tendrás que agregar esa entrada en Verse.
Para hacer esto, puedes verificar si un jugador ya está en el weak_map cada vez que accedes a él, o puedes agregar datos predeterminados al weak_map cada vez que se une un jugador, lo cual puedes saber si te suscribes al evento PlayerAddedEvent() del juego.
GetPlayspace().PlayerAddedEvent().Subscribe(OnPlayerAdded)
# Later in your file
OnPlayerAdded(Player:player):void=
if:
not PlayerProfileDataMap[Player]
set PlayerProfileDataMap[Player] = player_profile_data{}