NO MOM
I CANT PAUSE.
Scientific Number Tools Documentación
Soporte
Explorar lecciones

11. Guarda y recupera números con SaveGame de Unreal

Construye este ejemplo en tu proyecto de Unreal y comprueba el resultado en cada paso.

En esta página

Vas a crear una partida, guardar cuatro valores y recuperarlos después de cerrar Unreal. Usarás SaveGame de Unreal para el almacenamiento y los nodos de Scientific Number Tools para preparar y restaurar los valores Safe. La partida local de este ejemplo no cifra ni autentica el archivo. Safe protege el valor mientras vive en memoria; esa protección no convierte el archivo guardado en un registro seguro.

Crea tu objeto de partida

  1. En ScientificNumberPractice/Blueprints, pulsa botón derecho → Blueprint Class.
  2. En All Classes, busca SaveGame, selecciónala como clase padre y pulsa Select. Nombra el Blueprint BP_MiPartida.
  3. Ábrelo y añade las cuatro variables de la tabla. Selecciona cada variable y activa Save Game en sus detalles avanzados. Compila y guarda.

Los valores de la última columna se asignarán al guardar; no necesitas introducirlos como valores predeterminados del asset.

Variable Tipo Valor de la práctica
NormalValue Scientific Number 12345
PackedValue Packed Scientific Number 1250 (1.25 × 10³)
SafeLogicalValue Scientific Number 23456
BoundLogicalValue Scientific Number 34567

Importante: esta tabla describe las variables de BP_MiPartida, el objeto que vas a guardar. SafeLogicalValue y BoundLogicalValue deben ser de tipo Scientific Number normal. Sus nombres indican de dónde procede el dato, no el tipo protegido de la variable. NormalValue también es Scientific Number; solo PackedValue usa Scientific Number Packed.

En BP_MiGuardado trabajas con los valores protegidos en memoria: Try Make Safe Scientific Number produce un Safe Scientific Number, y SaldoContexto es Context Bound Safe Scientific Number. Los nodos Try Prepare … for Save comprueban esa protección y devuelven Out Value de tipo Scientific Number normal. Es esa salida la que asignas a SafeLogicalValue o BoundLogicalValue dentro de Partida.

Momento Safe Context-Bound
En memoria, antes de preparar Safe Scientific Number Context Bound Safe Scientific Number
En BP_MiPartida, después de Prepare SafeLogicalValue: Scientific Number BoundLogicalValue: Scientific Number
Al cargar, después de Restore Out Safe Value: Safe Scientific Number Out Safe Value: Context Bound Safe Scientific Number

Si ya creaste SafeLogicalValue como Safe Scientific Number o BoundLogicalValue como Context Bound Safe Scientific Number: abre BP_MiPartida, cambia ambas a Scientific Number, compila y guarda. Conserva la variable SaldoContexto del Actor como Context Bound Safe Scientific Number. Si habías creado setters de las variables de Partida, revisa sus pines tras compilar; vuelve a crearlos desde Get Partida si conservan el tipo anterior.

Guardar directamente las estructuras protegidas no sustituye este proceso: su protección pertenece a la ejecución actual. Prepare extrae el valor lógico y Restore crea una nueva protección de memoria al cargar. En este ejercicio el archivo sigue sin estar cifrado ni autenticado.

Prepara el Actor que ejecutará la prueba

Crea un Actor Blueprint BP_MiGuardado en Blueprints y colócalo en L_MiPractica. Para esta prueba deja solo ese Actor de prácticas en el nivel. Añade una variable booleana CargarAlIniciar, inicialmente False. Conecta BeginPlay → Branch, usando esa variable como Condition. Construye el flujo de guardar desde False y el de cargar desde True. Así podrás elegir una operación sin sobrescribir el archivo antes de leerlo.

Guardar: dónde construir los nodos

Todo el flujo siguiente se construye en el EventGraph de BP_MiGuardado. BP_MiPartida solo contiene las cuatro variables que creaste; no necesitas añadirle estos nodos ni abrir su EventGraph.

Hay dos operaciones con nombres parecidos: Set Partida conserva la referencia al objeto que acabas de crear. Set Normal Value, Set Packed Value, Set Safe Logical Value y Set Bound Logical Value escriben dentro de ese objeto. En estos cuatro setters, el pin Target debe recibir un Get de Partida. El cable azul indica sobre qué objeto trabajar; los cables blancos indican cuándo se ejecuta cada escritura.

Guardar A. Crear y conservar el objeto

  1. En BP_MiGuardado → EventGraph, conecta False del Branch de CargarAlIniciar a Create Save Game Object. En Save Game Class selecciona BP_MiPartida.
  2. Pulsa botón derecho sobre Return Value → Promote to Variable. Nombra la variable Partida y comprueba que su tipo es BP Mi Partida Object Reference.
  3. Conecta Return Value al pin azul de Set Partida y la salida blanca de Create Save Game Object a la entrada blanca de Set Partida.

Hasta aquí: BeginPlay → Branch (False) → Create Save Game Object → Set Partida. Si ya tienes esta cadena, continúa desde la salida blanca de Set Partida. Todavía no has escrito un archivo.

Guardar B. Escribir NormalValue en Partida

  1. Sigue en el mismo EventGraph. En My Blueprint → Variables, arrastra Partida a un espacio libre del grafo y elige Get Partida. No elijas Set Partida otra vez.
  2. Arrastra un cable desde el pin azul de salida de Get Partida, suéltalo en un espacio vacío y busca Set Normal Value (la variable se llama NormalValue). Selecciónalo. Unreal conectará Get Partida al pin Target del nuevo nodo.
  3. Conecta la salida blanca de Set Partida que ya tenías a la entrada blanca de Set Normal Value.
  4. Añade Make Scientific Number: Base = 12345, Exponent = 0.
  5. Conecta Return Value de Make Scientific Number al pin de valor Normal Value de Set Normal Value. No lo conectes a Target: Target es el objeto Partida, mientras Normal Value es el número que quieres escribir.
  6. Compila. La cadena blanca debe ser Create Save Game Object → Set Partida → Set Normal Value. Guarda el Blueprint.

Si no aparece Set Normal Value: abre BP_MiPartida, comprueba que existe la variable NormalValue, que no está marcada como Private, y compila ese Blueprint. Vuelve a BP_MiGuardado y busca arrastrando desde Get Partida; el tipo de Partida debe ser BP Mi Partida Object Reference, no la clase base SaveGame.

Qué acabas de hacer: el objeto Partida tiene ahora NormalValue = 12345 en memoria. Los siguientes bloques rellenan las otras tres variables; el archivo se escribe al final, en Guardar F.

Guardar C. Escribir PackedValue

  1. A la derecha de Set Normal Value, añade Make Scientific Number, Base = 1.25, Exponent = 3.
  2. Conecta su Return Value a Number de Try To Packed Number. Este nodo es puro: no lleva cables blancos.
  3. Añade un Branch. Conecta la salida blanca de Set Normal Value a su entrada blanca y Return Value de Try To Packed Number a Condition.
  4. Arrastra otro Get Partida al grafo. Desde su pin azul busca Set Packed Value; Get Partida queda conectado a Target.
  5. Conecta True del Branch a la entrada blanca de Set Packed Value. Conecta Out Packed de Try To Packed Number al pin de valor Packed Value.
  6. En False del Branch, añade Print String con No se pudo preparar Packed y termina esa rama sin guardar. El siguiente bloque continúa desde la salida blanca de Set Packed Value.

Guardar D. Escribir SafeLogicalValue

  1. Desde la salida blanca de Set Packed Value, conecta Try Make Safe Scientific Number. En In Value conecta Make Scientific Number, Base = 23456, Exponent = 0.
  2. Conecta su salida blanca a un Branch y su Return Value a Condition. En False imprime No se pudo crear Safe y termina la rama.
  3. Desde True ejecuta Try Prepare Safe Number for Save. Conecta Out Safe Value del nodo de creación a In Safe Value del nodo de preparación.
  4. Conecta la salida blanca de Prepare a otro Branch y Return Value a Condition. En False conecta Out Error a Print Scientific Number Error y termina la rama.
  5. Añade Get Partida. Desde su pin azul busca Set Safe Logical Value: Get Partida va a Target. Conecta True del último Branch a su entrada blanca y Out Value de Prepare a Safe Logical Value.

Aquí guardas un Scientific Number lógico en el objeto Partida. El valor Safe original y su protección de memoria no se escriben directamente en el archivo.

Guardar E. Escribir BoundLogicalValue

  1. En las variables de BP_MiGuardado, crea SaldoContexto, de tipo Context Bound Safe Scientific Number, y DominioContexto, de tipo Guid. Compila.
  2. Arrastra DominioContexto al grafo y elige Set. Conecta la salida blanca de Set Safe Logical Value a este Set DominioContexto. Añade New Guid y conecta su Return Value al valor del Set. Generas y conservas el GUID una sola vez.
  3. Después de Set DominioContexto ejecuta Set Context-Bound Safe Number. Conecta Get SaldoContexto a In Out Safe Value, Make Scientific Number (Base 34567, Exponent 0) a In Value, y Get DominioContexto a GUID. Escribe Coins en Context Name.
  4. Comprueba Return Value con un Branch conectado a su salida blanca. En False imprime No se pudo crear Context-Bound y termina la rama.
  5. Desde True ejecuta Try Prepare Context-Bound Safe Number for Save. Conecta Get SaldoContexto a In Safe Value, Get DominioContexto a GUID y escribe Coins en Context Name. No conectes un New Guid aquí: debes reutilizar el que guardaste en DominioContexto.
  6. Comprueba el bool de Prepare con otro Branch. En False imprime su Out Error mediante Print Scientific Number Error y termina la rama.
  7. Añade Get Partida. Desde su pin azul busca Set Bound Logical Value. Conecta Get Partida a Target, True del último Branch a la entrada blanca y Out Value de Prepare a Bound Logical Value.

Guardar F. Escribir el archivo, después de rellenar las cuatro variables

  1. Añade Save Game to Slot a la derecha de Set Bound Logical Value. Conecta la salida blanca de Set Bound Logical Value a la entrada blanca de Save Game to Slot.
  2. Añade Get Partida y conecta su pin azul a Save Game Object de Save Game to Slot. Es el mismo objeto que creaste al principio y al que has asignado los cuatro valores; no crees otro objeto aquí.
  3. En Save Game to Slot escribe Slot Name = MiPartidaNumeros y User Index = 0.
  4. Conecta su salida blanca a un Branch y Return Value a Condition. En True añade Print String con Partida guardada; en False, Print String con No se pudo guardar.
  5. Compila y guarda BP_MiGuardado. Con CargarAlIniciar = False, pulsa Play.

Qué debes ver: Partida guardada. Ese mensaje sale únicamente después de rellenar las cuatro variables y de que Unreal confirme la escritura del archivo. Si aparece un error en un bloque anterior, esa rama debe terminar sin llegar a Save Game to Slot.

Cargar después de cerrar el editor

  1. Ejecuta una vez con CargarAlIniciar = False y comprueba que aparece Partida guardada. Detén Play. Cambia CargarAlIniciar = True en los Class Defaults de BP_MiGuardado, compila y guarda el Blueprint y el nivel. Cierra Unreal y vuelve a abrir tu proyecto y L_MiPractica. Al pulsar Play se ejecutará la rama de carga, sin volver a guardar primero.
  2. Desde True del Branch de BeginPlay, comprueba Does Save Game Exist, Slot Name = MiPartidaNumeros y User Index = 0. Si existe, ejecuta Load Game from Slot con esos mismos parámetros. Conecta Return Value a Cast To BP_MiPartida y usa As BP Mi Partida para leer sus variables. Si el archivo no existe o falla el Cast, muestra No se pudo cargar y detén esa ruta sin inventar un saldo.
  3. Lee NormalValue y PackedValue directamente; comprueba que conservan 12345 y 1250.
  4. Pasa SafeLogicalValue a Try Restore Safe Number from Save. Comprueba su bool y, solo si tiene éxito, lee el resultado con Try Get Safe Number. Debe dar 23456.
  5. Asigna una vez un New Guid a DominioContexto en esta rama de carga. Pasa BoundLogicalValue a Try Restore Context-Bound Safe Number from Save, con Get DominioContexto en GUID y Coins en Context Name. Comprueba el bool y lee Out Safe Value con Try Get Context-Bound Safe Number, reutilizando ese mismo GUID y nombre. La lectura debe dar 34567. Estás creando una instancia Safe nueva en el contexto de esta ejecución.

Qué debes ver: al mostrar las cuatro lecturas con etiquetas y dos decimales, aparecen Normal: 12345.00, Packed: 1250.00, Safe: 23456.00 y Context-Bound: 34567.00. Para Packed, usa Unpack Scientific Number antes de formatear. No conectes los valores originales a estas impresiones: deben proceder del objeto cargado.

Límite de seguridad

Esta receta enseña serialización local de Unreal y el puente de tipos de SNT. El contenido SafeLogicalValue y BoundLogicalValue es un Scientific Number legible; ni SaveGame ni los nodos Prepare/Restore lo cifran o autentican en disco. La restauración reconstruye protección en memoria, pero no demuestra que el dato cargado sea auténtico.

En esta práctica has guardado y cargado los cuatro valores usando SaveGame de Unreal. ScientificNumberTools no incluye un selector de proveedores ni conecta automáticamente con servicios de guardado. Si tu juego utiliza otro sistema de persistencia, tu código Blueprint o C++ llama a Prepare antes de entregar el número a ese sistema y a Restore después de recuperarlo. Los valores Normal y Packed se entregan directamente, sin esos pasos de conversión.

Ese sistema puede sustituir SaveGame o utilizarlo internamente. Si necesitas proteger los datos guardados contra manipulación, esa protección y su verificación corresponden al sistema de persistencia del juego. Restore reconstruye el valor protegido en memoria; no verifica la autenticidad del archivo ni la autorización del saldo cargado.