Issue saving/loading instance editable bool c++

Hi,

I am getting crazy about this. I want to save a boolean which is also instance editable (EditAnywhere) but somehow, when I change the value in the instance, it’s not saving it.

I also tried other variable types and it works just fine there.

This it how the actor looks like in c++:

UCLASS()
class GAME_API ATestSaveActor : public AActor
{
	GENERATED_BODY()

public:
	// Sets default values for this actor's properties
	ATestSaveActor();

	UPROPERTY(EditAnywhere, SaveGame)
	bool BoolValue = false;

	UPROPERTY(EditAnywhere, SaveGame)
	FString StringValue = "InitialValue";

protected:
	// Called when the game starts or when spawned
	virtual void BeginPlay() override;

public:
	// Called every frame
	virtual void Tick(float DeltaTime) override;
};

I place two of those actors in the world and change the bool of one of them to “TRUE”. Ingame I just flip both values and save the game (also checking for correct value with logs). When loading again both actors have BoolValue == “TRUE”. Somehow the instance-edited value doesn’t get loaded (or saved) properly. As far as I tested it’s only happening with bool values.

Any hints?

1 Like

Okay, after a while I looked into this again and found the problem.

I was using Actor->GetName() instead of Actor->GetFName() as reference to store and restore the data. Should have posted more code I guess. The other variables worked just on coincidence i assume, as the actors where kinda mixed.

UPDATE:

Unfortunately, I was a little too fast in thinking it’s solved, IT ISNT! :frowning:
Even though the FName played a role here, it’s not solving the bool thing.

I’ve created a naked project to have a clean test environment, set all up as described above and tried with a single actor.

The instance edited bools always return to their ‘instance edited’ value after loading.

This is the code I use for saving/loading:

USTRUCT()
struct FActorSaveData
{
	GENERATED_BODY()

public:
	UPROPERTY()
	FName ActorName;
	
	UPROPERTY()
	TArray<uint8> ByteData;
};

// Saving

auto SaveGame = NewObject<UMySaveGame>(this, TEXT("SaveGame"));
	for (FActorIterator It(GetWorld()); It; ++It)
	{
		TObjectPtr<AActor> Actr = *It;
		if (auto Actor = Cast<ATestActor>(Actr))
		{
			Actor->OutputValuesLog();
			FActorSaveData ActorData;
			ActorData.ActorName = Actor->GetFName();

			FMemoryWriter MemWriter(ActorData.ByteData);
			FObjectAndNameAsStringProxyArchive Ar(MemWriter, true);
			Ar.ArIsSaveGame = true;
			
			Actr->Serialize(Ar);
			
			SaveGame->ActorSaveData.Add(ActorData);
		}
	}
	UGameplayStatics::SaveGameToSlot(SaveGame, TEXT("SLOT0"), 0);


// Loading

if (const auto SaveGame = Cast<UMySaveGame>(UGameplayStatics::LoadGameFromSlot(TEXT("SLOT0"), 0)))
	{
		for (FActorIterator It(GetWorld()); It; ++It)
		{
			TObjectPtr<AActor> Actr = *It;
			if (auto Actor = Cast<ATestActor>(Actr))
			{
				for (auto SaveData : SaveGame->ActorSaveData)
				{
					if (SaveData.ActorName.IsEqual(Actor->GetFName()))
					{
						FMemoryReader MemReader(SaveData.ByteData);
						FObjectAndNameAsStringProxyArchive Ar(MemReader, true);
						Ar.ArIsSaveGame = true;
						Actor->Serialize(Ar);
						Actor->OutputValuesLog();
					}
				}
			}
		}
	}

The corresponding logs look like this:
(Changing variables, saving actor, loading actor )

LogTemp: Warning: ---- INITIAL VARIABLES ----   
LogTemp: Actor=TestActor1_C_UAID_2CF05D946BA0A9AB01_1122023479, 
   -> TestBoolA=TRUE   <--- INSTANCE EDITED TO TRUE
   -> TestBoolB=FALSE
   -> TestEnumA=ETestEnum::VALUE_B    <--- INSTANCE EDITED TO VALUE_B
   -> TestEnumB=ETestEnum::VALUE_B
   -> TestEnumC=ETestEnum::VALUE_C
   ->TestBoolPrivateA=FALSE
   ->TestBoolPrivateB=TRUE   <--- INSTANCE EDITED TO TRUE
   
LogTemp: Warning: ---- CHANGED VARIABLES ----   
LogTemp: Actor=TestActor1_C_UAID_2CF05D946BA0A9AB01_1122023479, 
   -> TestBoolA=FALSE
   -> TestBoolB=TRUE
   -> TestEnumA=ETestEnum::VALUE_C
   -> TestEnumB=ETestEnum::VALUE_B
   -> TestEnumC=ETestEnum::VALUE_A
   ->TestBoolPrivateA=TRUE
   ->TestBoolPrivateB=FALSE

LogTemp: Warning: ---- SAVING ACTOR ----

LogTemp: Warning: ---- LOADED ACTOR ----
LogTemp: Actor=TestActor1_C_UAID_2CF05D946BA0A9AB01_1122023479, 
   -> TestBoolA=TRUE
   -> TestBoolB=TRUE
   -> TestEnumA=ETestEnum::VALUE_C
   -> TestEnumB=ETestEnum::VALUE_B
   -> TestEnumC=ETestEnum::VALUE_A
   ->TestBoolPrivateA=TRUE
   ->TestBoolPrivateB=TRUE

All fields of the TestActor have properties EditAnywhere and SaveGame
The instance edited bools always stick to their value.
Btw., I am working with UE5.2.1

1 Like