Serialization of default-constructed members?

Premise:
I have been writing a saving system that relies on the SaveGame flag and the FArchive class hierarchy.
So far I can save any actor in my world and restore it. However, it seems like when serializing an actor that has a member that is still default-initialized and has the SaveGame flag enabled, it will NOT get serialized.

Question:
Why do default-constructed members with the SaveGame flag not get serialized when calling serialize on an actor? Also, how can I change that?

Context/Problem:
Upon trying to load all actors in a level without opening the level again (simply search for every actor’s save-entry and restore his data), I have encountered that default-initialized members of an actor or his components, do NOT get serialized.

So if my health default value is 100, I then save my actor, then get damaged to 75 health, then load that actor again, he remains at 75 health. Other values work correctly though.
If I get damaged to health 75 first, then save, then get damaged to 50, then load, my health gets restored to 75 though.

This is not a problem when actually opening the level first, as a) values get stored when changed from default and b) values get default-initialized when the level gets opened. So, when loading a level anew, there is no problem. That’s why I have taken so long to encounter this problem, as I only encountered it when trying to implement quick save and quick load, which does not make use of re-opening a level.

I have been debugging and logging my code a lot, so errors on my part seem to be non-existant in this case (95% sure).

I have done some digging in the engine code, and it became apparent that a property, should it pass the “ShouldSerializeValue” check from Class.cpp, still doesn’t get serialized if the property in question has default values.

However, in the same check that refuses the default-initialized properties, the FArchive flag “ArNoDelta” gets checked too. So if you set the ArNoDelta flag of your FArchive (Proxy Archive in this case) to “true”, then the property will pass the check regardless of its default-values.

The documentation/comment of ArNoDelta is wrong, as it is just copy pasted from the property directly above it. I am not entirely sure if setting that flag to true will result in other changes as well, but for now, setting it to true circumvents this 2nd check and allows for default-values to be saved.

1 Like

Thank you, this was really helpful!