Los datos persistentes te permiten rastrear y guardar datos por jugador entre sesiones de juego. Los datos persistentes almacenan los datos de cada jugador, como su perfil o sus estadísticas, en Verse. Estos datos pueden actualizarse tantas veces como cambie su valor. Dado que estos datos son persistentes, se mantendrán a lo largo de las sesiones de juego y estarán disponibles siempre que el jugador esté conectado al juego. Para obtener más información, consulta Cómo usar datos de persistencia en Verse.
Esta página cubre algunas de las prácticas recomendadas para trabajar con datos persistentes en Verse.
Cómo utilizar clases para añadir nuevos campos más tarde
Actualmente, el único tipo de datos persistentes que puedes cambiar después de publicar la isla es el tipo class, siempre y cuando los nuevos campos tengan valores predeterminados. Esto significa que al cargar datos guardados de una versión anterior se incluirán los nuevos campos y sus valores predeterminados.
Veamos 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 = 0Desde que el proyecto está publicado y en funcionamiento en tiempo real, los jugadores que hayan jugado al juego tendrán estos datos persistentes asociados a ellos. Si añadimos más campos a los datos del perfil del jugador, como el recuento de misiones y el historial, los datos persistentes podrían tener el siguiente aspecto 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 los jugadores que hayan jugado con la primera versión de la clase player_profile_data incluirán ahora los nuevos campos:
CompletedQuestCountcon un valor de0, que es el valor predeterminado que se ha especificado.QuestHistorycon una matriz de cadenas vacía, que es el valor predeterminado que se ha especificado.
Esto funciona porque se proporcionó un valor predeterminado para los nuevos campos para poder actualizar la versión anterior de los datos.
Como solo las clases pueden actualizarse después de publicar un proyecto, recomendamos una clase como tipo de valor de cualquier variable weak_map de ámbito de módulo.
Si quieres más información sobre cómo crear una clase persistente, consulta Tipos persistentes.
Uso de constructores para actualizaciones parciales
Si utilizas clases, te recomendamos que utilices un constructor para crear una nueva instancia de la clase que contenga el estado actualizado, ya que los constructores te permiten realizar actualizaciones parciales de las clases.
El siguiente ejemplo muestra cómo se puede actualizar PlayerProfileDataMap. La función GrantXP() obtiene los datos actuales del jugador indicado y, a continuación, llama al constructor MakePlayerProfileData() para crear una nueva versión de sus datos de perfil. Debido a que los datos de origen del jugador se pasan al constructor junto con el nuevo valor de PE, solo se actualizará el valor de PE mientras que todos los demás datos del jugador permanecerán iguales.
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 muestra cómo actualizar un campo, pero puedes actualizar tantos como necesites de esta manera:
set PlayerProfileDataMap[Player] = player_profile_data:
QuestHistory := UpdatedSaveData.QuestHistory
CompletedQuestCount := OldData.CompletedQuestCount + 1
MakePlayerProfileData<constructor>(OldData)Control de versiones de los datos de persistencia
Recomendamos utilizar el control de versiones en clases persistentes para detectar la versión de la instancia para los datos previamente guardados de un jugador. Al usar versiones, puedes detectar y aplicar migraciones si la definición de clase persistente o la lógica de juego cambian con el tiempo.
Aunque puedes utilizar valores enteros o de cadena para indicar la versión de la clase persistente, recomendamos utilizar valores de option para almacenar referencias a versiones actuales y pasadas de los datos. Considera 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 option tanto para la primera como para la segunda versión de la clase de datos asociada, que están representadas por las clases v1_player_data y v2_player_data. Solo se debe establecer siempre V1 o V2 para evitar que los jugadores tengan asociadas varias versiones de datos.
Los datos originales del jugador V1 contienen tres campos int. La versión V2 de los datos cambia el campo Playtime a un float, además de añadir dos nuevos campos. Como el tipo del campo Playtime ha cambiado en la versión V2, habrá que convertirlo para cualquier jugador que todavía tenga los datos antiguos de la V1. Cuando un jugador con datos antiguos de la V1 se une a una experiencia, puedes utilizar las funciones constructoras auxiliares para compilar una nueva clase de datos de la V2 basada en los datos antiguos, así:
# 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
Puede haber ocasiones en las que tengas que forzar un restablecimiento de datos en los jugadores que se unan a tu isla. Para ello, reasigna un valor predeterminado para los datos de persistencia en el `weak_map` en todos los jugadores y cambia el campo Version de la clase. Si utilizas datos opcionales de versiones, puedes restablecer los datos estableciendo los campos opcionales en false.
Para saber si los datos del jugador ya se han restablecido, puedes verificar el valor de Version en los datos de persistencia del jugador y así comprobar si es la última.
Cómo verificar que los datos de persistencia están dentro de los límites
Si la actualización puede afectar al tamaño total de los datos persistentes, debes verificar que los datos persistentes aún se ajusten a las restricciones del sistema de persistencia de Verse. Si intentas actualizar los datos persistentes y superan los límites de tamaño, obtendrás un error en tiempo de ejecución de Verse. Consulta Tamaño máximo de objeto persistente si quieres más información.
Puedes comprobar cómo afectan las actualizaciones al tamaño total mediante la función FitsInPlayerMap().
En el siguiente ejemplo, los datos persistentes contienen una matriz de cadenas. Si esa matriz alguna vez se vuelve demasiado grande para almacenarla en débil_map, como cuando falla FitsInPlayerMap(), 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 cuando un jugador se une a tu isla
Cuando un nuevo jugador se una a la isla, no se le añadirá una entrada automáticamente al weak_map persistente. Tendrás que añadir esa entrada en Verse.
Para ello, puedes comprobar si un jugador ya está en el weak_map cada vez que accedas a él o puedes añadir datos predeterminados al weak_map cada vez que un jugador se una, para lo cual puedes suscribirte 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{}