When serializing properties, class default values are not saved. This is fine when actors are spawned from the class, but if the actor already exists in the scene and the level designer sets the value to a non-class default, changing that value back to the default during gameplay will not properly save state.
Reproduction steps:
1. Create a blueprint class with an int variable (with default 0)
2. Place an instance of this actor in the level, and change the int's value to 5
3. During runtime, change the int's value back to default (0)
4. Save the game (int value of 0 is expected to be saved)
5. Stop the game and relauch PIE
6. Load the game
7. Result: The int's value is NOT 0, but the level's default 5 [because the property wasn't saved]
Do you mean that you change the value during PIE through the detail’s pane?
Changes made during PIE will not save value changes, this must be done while not in PIE. If you intend to use a save/load functionality to save an instance of the integer value, please read over this documentation, which covers the proper method to save and load data during PIE.
A bit of background for the save method I am using: I’m using the SaveGame object serialized with an FObjectAndNameAsStringProxyArchive with “ArIsSaveGame = true” (C++).
The problem is when a property of an actor is changed in the editor by a level designer (not PIE), and later that value is changed back to the (class) default value through code [eg. character’s mood default value is ‘neutral’, the designer sets it to ‘sad’ through the details panel, and during the game the character stops being sad and set to ‘neutral’ again ← the property is ignored during save when default, so on load it will be the ‘sad’ state, set by the designer].
I’ve tracked it to UObject’s SerializeScriptProperties method which seems to purposefully ignore properties set to class defaults, but this means it will not save or restore the proper state if the actor instance’s property is set it to anything but it’s default value.
Hi , to reproduce this in a new project, you’ll need to first add the ability to save whole actors using the SaveGame flag to save the properties on the actor. (eg. saving MyActor will save it’s property MyInt automatically, because it has the SaveGame flag on).
Once you have that, the steps in my original post should re-create the issue (note: the actor instance should be added to the SaveGameObject before saving).
Digging a bit deeper in the serialize code, I found ArNoDelta = true seems to force the properties to serialize (please correct me if I am misusing this flag).
So far as my testing goes, this flag has resolved my issue and the original behavior seems to be intentional (an optimization I would assume is valid in usual cases).
Thanks for this I just ran into the same problem! I am using the USaveGame object and the helpers in UGameplayStatics (like SaveGameToSlot), so I modified the code there to use that flag on the archive.
Epic - Whilst I understand the optimsation to not save out values the same as the defaults, I am a little confused as to why it doesnt delete the old value from the saved file. How does the old value that was different from the default, stay in the saved file, if the current property is now different (but identical to the default objects value).