11. Save and restore numbers with Unreal SaveGame
Build this example in your Unreal project and compare the result at each step.
On this page
- Create your save-game object
- Prepare the Actor that will run the test
- Saving: where to build the nodes
- Saving A. Create and keep the object
- Saving B. Write NormalValue to Partida
- Saving C. Write PackedValue
- Saving D. Write SafeLogicalValue
- Saving E. Write BoundLogicalValue
- Saving F. Write the file after filling all four variables
- Load after closing the editor
- Security boundary
You will create a save game, store four values, and recover them after closing Unreal. You will use Unreal SaveGame for storage and Scientific Number Tools nodes to prepare and restore Safe values. This example’s local save file is not encrypted or authenticated. Safe protects the value while it lives in memory; that protection does not make the saved file secure.
Create your save-game object
- In ScientificNumberPractice/Blueprints, right-click → Blueprint Class.
- Under All Classes, search for SaveGame, select it as the parent class, and click Select. Name the Blueprint BP_MiPartida.
- Open it and add the four variables in the table. Select each variable and enable Save Game in its advanced details. Compile and save.
The values in the last column will be assigned when saving; you do not need to enter them as the asset’s default values.
| Variable | Type | Exercise value |
|---|---|---|
| NormalValue | Scientific Number | 12345 |
| PackedValue | Packed Scientific Number | 1250 (1.25 × 10³) |
| SafeLogicalValue | Scientific Number | 23456 |
| BoundLogicalValue | Scientific Number | 34567 |
Important: this table describes the variables in BP_MiPartida, the object you will save. SafeLogicalValue and BoundLogicalValue must be of type Scientific Number normal. Their names indicate where the data comes from, not the protected type of the variable. NormalValue is also Scientific Number; only PackedValue uses Scientific Number Packed.
In BP_MiGuardado you will work with protected values in memory: Try Make Safe Scientific Number produces a Safe Scientific Number, and SaldoContexto is Context Bound Safe Scientific Number. The Try Prepare … for Save nodes check that protection and return Out Value of type normal Scientific Number. That is the output you assign to SafeLogicalValue or BoundLogicalValue in Partida.
| Moment | Safe | Context-Bound |
|---|---|---|
| In memory, before preparing | Safe Scientific Number | Context Bound Safe Scientific Number |
| In BP_MiPartida, after Prepare | SafeLogicalValue: Scientific Number | BoundLogicalValue: Scientific Number |
| On load, after Restore | Out Safe Value: Safe Scientific Number | Out Safe Value: Context Bound Safe Scientific Number |
If you already created SafeLogicalValue as Safe Scientific Number or BoundLogicalValue as Context Bound Safe Scientific Number: open BP_MiPartida, change both to Scientific Number, compile, and save. Keep the SaldoContexto variable on the Actor as Context Bound Safe Scientific Number. If you created setters for the Partida variables, check their pins after compiling; recreate them from Get Partida if they still have the old type.
Saving the protected structs directly does not replace this process: their protection belongs to the current execution. Prepare extracts the logical value, and Restore creates new in-memory protection on load. In this exercise the file is still not encrypted or authenticated.
Prepare the Actor that will run the test
Create an Actor Blueprint BP_MiGuardado in Blueprints and place an instance in L_MiPractica. For this test, leave only that practice Actor in the level. Add a Boolean variable CargarAlIniciar, initially False. Connect BeginPlay → Branch, using that variable as the Condition. Build the save flow from False and the load flow from True. This lets you choose an operation without overwriting the file before reading it.
Saving: where to build the nodes
Build the entire flow below in the EventGraph of BP_MiGuardado. BP_MiPartida only contains the four variables you created; you do not need to add these nodes to it or open its EventGraph.
There are two similarly named operations: Set Partida keeps a reference to the object you just created. Set Normal Value, Set Packed Value, Set Safe Logical Value, and Set Bound Logical Value write inside that object. For these four setters, the Target pin must receive a Get of Partida. The blue wire indicates which object to work on; the white wires indicate when each write executes.
Saving A. Create and keep the object
- In BP_MiGuardado → EventGraph, connect False from the CargarAlIniciar Branch to Create Save Game Object. Set Save Game Class to BP_MiPartida.
- Right-click Return Value → Promote to Variable. Name the variable Partida and check that its type is BP Mi Partida Object Reference.
- Connect Return Value to the blue pin on Set Partida and the white output of Create Save Game Object to the white input of Set Partida.
So far: BeginPlay → Branch (False) → Create Save Game Object → Set Partida. If you already have this chain, continue from the white output of Set Partida. You have not written a file yet.
Saving B. Write NormalValue to Partida
- Stay in the same EventGraph. In My Blueprint → Variables, drag Partida into an empty area of the graph and choose Get Partida. Do not choose Set Partida again.
- Drag a wire from the blue output pin on Get Partida, drop it in an empty area, and search for Set Normal Value (the variable is named NormalValue). Select it. Unreal will connect Get Partida to the new node’s Target pin.
- Connect the white output of the Set Partida node you already have to the white input of Set Normal Value.
- Add Make Scientific Number: Base =
12345, Exponent =0. - Connect Return Value from Make Scientific Number to the Normal Value value pin on Set Normal Value. Do not connect it to Target: Target is the Partida object, while Normal Value is the number you want to write.
- Compile. The white chain should be
Create Save Game Object → Set Partida → Set Normal Value. Save the Blueprint.
If Set Normal Value does not appear: open BP_MiPartida, check that the NormalValue variable exists and is not marked Private, and compile that Blueprint. Return to BP_MiGuardado and search by dragging from Get Partida; the type of Partida must be BP Mi Partida Object Reference, not the SaveGame base class.
What you just did: the Partida object now has NormalValue = 12345 in memory. The following blocks fill in the other three variables; the file is written at the end, in Saving F.
Saving C. Write PackedValue
- To the right of Set Normal Value, add Make Scientific Number, Base =
1.25, Exponent =3. - Connect its Return Value to Number on Try To Packed Number. This node is pure: it has no white wires.
- Add a Branch. Connect the white output of Set Normal Value to its white input, and Return Value from Try To Packed Number to Condition.
- Drag another Get Partida into the graph. From its blue pin, search for Set Packed Value; Get Partida will be connected to Target.
- Connect True from the Branch to the white input of Set Packed Value. Connect Out Packed from Try To Packed Number to the Packed Value value pin.
- On False from the Branch, add Print String with
Could not prepare Packedand end that branch without saving. The next block continues from the white output of Set Packed Value.
Saving D. Write SafeLogicalValue
- From the white output of Set Packed Value, connect Try Make Safe Scientific Number. Connect Make Scientific Number with Base =
23456, Exponent =0to In Value. - Connect its white output to a Branch and its Return Value to Condition. On False, print
Could not create Safeand end that branch. - From True, execute Try Prepare Safe Number for Save. Connect Out Safe Value from the creation node to In Safe Value on the preparation node.
- Connect the white output of Prepare to another Branch and Return Value to Condition. On False, connect Out Error to Print Scientific Number Error and end that branch.
- Add Get Partida. From its blue pin, search for Set Safe Logical Value: Get Partida goes to Target. Connect True from the last Branch to its white input and Out Value from Prepare to Safe Logical Value.
Here you save a logical Scientific Number in the Partida object. The original Safe value and its in-memory protection are not written directly to the file.
Saving E. Write BoundLogicalValue
- In the variables of BP_MiGuardado, create SaldoContexto, of type Context Bound Safe Scientific Number, and DominioContexto, of type Guid. Compile.
- Drag DominioContexto into the graph and choose Set. Connect the white output of Set Safe Logical Value to this Set DominioContexto. Add New Guid and connect its Return Value to the value of the Set. Generate and keep the GUID once.
- After Set DominioContexto, execute Set Context-Bound Safe Number. Connect Get SaldoContexto to In Out Safe Value, Make Scientific Number (Base
34567, Exponent0) to In Value, and Get DominioContexto to GUID. EnterCoinsin Context Name. - Check Return Value with a Branch connected to its white output. On False, print
Could not create Context-Boundand end that branch. - From True, execute Try Prepare Context-Bound Safe Number for Save. Connect Get SaldoContexto to In Safe Value, Get DominioContexto to GUID, and enter
Coinsin Context Name. Do not connect a New Guid here: reuse the one you stored in DominioContexto. - Check the Prepare bool with another Branch. On False, print its Out Error using Print Scientific Number Error and end that branch.
- Add Get Partida. From its blue pin, search for Set Bound Logical Value. Connect Get Partida to Target, True from the last Branch to the white input, and Out Value from Prepare to Bound Logical Value.
Saving F. Write the file after filling all four variables
- Add Save Game to Slot to the right of Set Bound Logical Value. Connect the white output of Set Bound Logical Value to the white input of Save Game to Slot.
- Add Get Partida and connect its blue pin to Save Game Object on Save Game to Slot. This is the same object you created at the start and assigned all four values to; do not create another object here.
- In Save Game to Slot, enter Slot Name =
MiPartidaNumerosand User Index =0. - Connect its white output to a Branch and Return Value to Condition. On True, add Print String with
Game saved; on False, Print String withCould not save. - Compile and save BP_MiGuardado. With CargarAlIniciar = False, press Play.
What you should see: Game saved. This message appears only after all four variables have been filled and Unreal confirms the file write. If an earlier block reports an error, that branch should end without reaching Save Game to Slot.
Load after closing the editor
- Run once with CargarAlIniciar = False and check that
Game savedappears. Stop Play. Change CargarAlIniciar = True in Class Defaults for BP_MiGuardado, compile and save the Blueprint and level. Close Unreal, reopen your project and L_MiPractica. When you press Play, the load branch will run without saving first. - From True on the BeginPlay Branch, check Does Save Game Exist, with Slot Name =
MiPartidaNumerosand User Index =0. If it exists, execute Load Game from Slot with those same parameters. Connect Return Value to Cast To BP_MiPartida and use As BP Mi Partida to read its variables. If the file does not exist or the Cast fails, showCould not loadand end that path without inventing a balance. - Read
NormalValueandPackedValuedirectly; check that they retain 12345 and 1250. - Pass
SafeLogicalValueto Try Restore Safe Number from Save. Check its bool and, only if it succeeds, read the result with Try Get Safe Number. It should return 23456. - Assign a New Guid to DominioContexto once in this load branch. Pass
BoundLogicalValueto Try Restore Context-Bound Safe Number from Save, with Get DominioContexto on GUID andCoinsin Context Name. Check the bool and read Out Safe Value with Try Get Context-Bound Safe Number, reusing that same GUID and name. The read should return 34567. You are creating a new Safe instance in this execution context.
What you should see: when you display all four reads with labels and two decimal places, they appear as Normal: 12345.00, Packed: 1250.00, Safe: 23456.00, and Context-Bound: 34567.00. For Packed, use Unpack Scientific Number before formatting. Do not connect the original values to these prints: they must come from the loaded object.
Security boundary
This recipe teaches local Unreal serialization and the SNT type bridge. The contents of SafeLogicalValue and BoundLogicalValue are readable Scientific Numbers; neither SaveGame nor the Prepare/Restore nodes encrypt or authenticate them on disk. Restore rebuilds in-memory protection, but does not prove that the loaded data is authentic.
In this exercise you saved and loaded all four values using Unreal SaveGame. ScientificNumberTools does not include a provider selector or automatically connect to save services. If your game uses another persistence system, your Blueprint or C++ code calls Prepare before handing the number to that system and Restore after retrieving it. Normal and Packed values are passed directly, without those conversion steps.
That system can replace SaveGame or use it internally. If you need to protect saved data against tampering, that protection and its verification belong to the game’s persistence system. Restore rebuilds the protected value in memory; it does not verify the file’s authenticity or authorize the loaded balance.