I have created a USaveGame subclass in blueprint, called BP_SaveGame.
This subclass has two properties, a FString, and an UObject subclass that I have defined in C++.
Both are marked “SaveGame” in the blueprint.
The properties of the C++ object are also marked SaveGame (as well as BluprintReadWrite and EditableAnywhere)
The properties on the C++ object are TArray<>s of FStructs, which in turn also have their properties marked as SaveGame.
In blueprint, I create a BP_SaveGame class instance. I then create the UObject subclass, and put a bunch of data into the TArrays<> in C++ code, and then I assign this object to the property in the BP_SaveGame.
I save the SaveGame to a slot using Async Save Game to Slot.
However, when this SaveGame object is actually saved, neither the property that contains the string nor the property that contains the UObject subclass are actually serialized.
The data is not in the archive .sav file on disk, and the PreSave(Platform) callback doesn’t get called on my object instance.
When I load the SaveGame object back, it comes back as the right class (BP_SaveGame) but of course contains no property values.
Why are these properties on the BP_SaveGame not getting serialized?
From the blueprint that actually tries to save the state:
From the BP_SaveGame, the highlighted Put Character Data function:
The property definition that contains the Character Save:
Slurping the data into the UCarriedInventory object:
UCLASS(Blueprintable, ClassGroup=("Character Sheet"), meta=(BlueprintSpawnableComponent))
class SCAPES_API UCharacterSheet : public UActorComponent {
...
UFUNCTION(BlueprintCallable, Category = "Stats and Skills|Inventory")
void SaveInventory(UCarriedInventory* ToInv);
void UCharacterSheet::SaveInventory(UCarriedInventory* ToInv) {
ToInv->Inventory.Reset();
ToInv->CharacterStats.Reset();
for (auto& it : Equipped) {
if (it.Value.Contents.StackCount > 0) {
it.Value.Contents.SaveConsumption();
ToInv->Inventory.Add(it.Value);
}
}
for (auto& it : Carried) {
if (it.Contents.StackCount > 0) {
ToInv->Inventory.Add(it);
}
}
for (auto& it : Stats) {
if (it.Value->Consumed != 0.0f) {
ToInv->CharacterStats.Add({
it.Key,
it.Value->Consumed
});
}
}
}
The UCarriedInventory object itself:
UCLASS(Blueprintable, Category="Stats and Skills|Inventory")
class SCAPES_API UCarriedInventory : public UObject {
GENERATED_BODY()
public:
UCarriedInventory();
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Stats and Skills|Inventory", SaveGame)
TArray<FEquipmentSlot> Inventory;
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Stats and Skills|Inventory", SaveGame)
TArray<FSavedStatConsumption> CharacterStats;
void PreSave(ITargetPlatform const *TargetPlatform) override;
void PostLoad() override;
};