Why does my savegame reset my struct?

USTRUCT()
struct FCreatureStats
{
GENERATED_BODY()

	int Deaths;
	float DamageTaken;
	float StaminaUsed;
	float HealthRegenerated;
	float StaminaRegenerated;
	
};
class UTitle;
UCLASS()
class UTitlesSaveGame : public USaveGame
{
	GENERATED_BODY()
	
	public:
	UTitlesSaveGame();

	UPROPERTY(VisibleAnywhere, Category = Basic)
	TArray<TSubclassOf<UTitle>> AllTitles;
	UPROPERTY(VisibleAnywhere, Category = Basic)
	FCreatureStats Stats;
};
void UTitles::InitTitles(UCreature* Parent)
{
	check(Parent);
	this->ParentCreature = Parent;
	Stats.Deaths +=1;
	EarnedTitles.Add(NewObject<UTitle>());
	SaveTitles();
	LoadTitles();
}

void UTitles::LoadTitles()
{
	EarnedTitles.Empty();
	if (UTitlesSaveGame* LoadedGame = Cast<UTitlesSaveGame>(UGameplayStatics::LoadGameFromSlot("Titles", 0)))
	{
		for(TSubclassOf<UTitle> Skill : LoadedGame->AllTitles)
		{
			UTitle* Sub = NewObject<UTitle>(ParentCreature, Skill.Get());
			EarnedTitles.Add(Sub);
		}
		Stats = LoadedGame->Stats;
	}
}

void UTitles::SaveTitles()
{
	if (UTitlesSaveGame* SaveGameInstance = Cast<UTitlesSaveGame>(UGameplayStatics::CreateSaveGameObject(UTitlesSaveGame::StaticClass())))
	{
		TArray<TSubclassOf<UTitle>> SubClass;
		for (UTitle* Title : EarnedTitles)
		{
			SubClass.Add(TSubclassOf<UTitle>(Title->GetClass()));
		}
		SaveGameInstance->AllTitles = SubClass;
		SaveGameInstance->Stats = Stats;
		if (UGameplayStatics::SaveGameToSlot(SaveGameInstance, "Titles", 0))
		{
			UE_LOG(LogClass, Log, TEXT("Saved Titles Successfully!"));
		}else
		{
			UE_LOG(LogClass, Error, TEXT("Failed to save Titles!"));
			
		}
	}
}

I checked that theoretically the right struct is saved with deaths = 1.

I added a testint in the savegame and its being loaded fine.

When loading the struct, deaths is being reseted to 0.

Do you have any special reason to do save then load at line 33 and 34 ?

Its just for testing purposes, normally only the loading is requiered but i wanted to overwrite the savefile faster for easier debug.

where are you holding referance of your saved game data? GameInstance ?
Actually the thing is careful if you are calling reference not the copy itself.

Im not holding a reference to the savegame, its being created in the load and save function and the data is saved to variables in the header.

UPROPERTY()
TArray<UTitle*> EarnedTitles;
UPROPERTY()
FCreatureStats Stats;

Earned Titles works (probably, i have a copy which works and doesnt use structs but only saves the class)
Stats doesnt work properly.

Ok what you can do is, think save game as just a UObject, means only saves saved game data. For the save and load you can use GameInstance class. Dont put any additional function inside of savegame class.

My Savgame classes:
TitlesSaveGame.h

#pragma once

#include "CoreMinimal.h"

#include "GameFramework/SaveGame.h"
#include "Skillz/Constructors/Titles.h"

#include "TitlesSaveGame.generated.h"

class UTitle;
UCLASS()
class UTitlesSaveGame : public USaveGame
{
	GENERATED_BODY()
	
public:
	UPROPERTY(VisibleAnywhere, Category = Basic)
	TArray<TSubclassOf<UTitle>> AllTitles;
	UPROPERTY(VisibleAnywhere, Category = Basic)
	FCreatureStats Stats;
};

TitlesSaveGame.cpp is empty
The allready posted code is a mix of Titles.h and Titles.cpp.

Does it make a difference if i store the savegame instance instead of just storing the variables directly?

when you need variables you will call them from referance that GameInstance holds. Otherwise its inevitible to have such issues. GameMode will control your scores and saves with the help of GameInstance. I hope I can shape design on your mind.

So i should create a gameinstance holding a reference to a savegame in the gamemode? I can try but i dont see how it would change the behavior. I tried debugging and the created savegame in the save function has the correct values, only loading changes it and i dont see how.

Here Some Debugging Logs :

As I understand what you try to achieve is as a design :


GameInstance

Create a GameInstance in cpp and have reference to your save game TitlesSaveGame, and have functions like

UPROPERTY(BlueprintReadOnly, Category = "Save Game")
class TitlesSaveGame* InstancedGameData;

// save game you can call with variables to be saved. Depends on your design.
UFUNCTION(BlueprintCallable, Category = "Save Game")
void SaveGame();

// here you can load your game.
void InitSaveGameSlot();

// These both functions are build in in game instance, UE will call them whenever game starts. Basically you can load your game in this function
void Init() override;

// Called by the game as it shuts down.
void Shutdown() override;

GameInstance is accessible from anywhere that you can call above functions to maintain your save/load game logic.
How to call game instance is

UGameInstance* GameInstance = Cast<UGameInstance>(UGameplayStatics::GetGameInstance(this));
// And later you can call your function like follows
if (GameInstance) // always check
{
    GameInstance->SaveGame();
}

can you just try single variable and save it then call ?

Works. Added an int to the savegame, serialized it to 9, incremented it in the save function and it loaded correctly as 10. Its just the struct that kepps on not loading.

youre welcome :slight_smile: Most probably you save copy of your struct not the itself. Its better to have in this way. Your game will get complicated in coding overtime. Keeping clear in the beginning will always help you later.

I have no clue why, but this worked! thanks.

Maybe creating a savegame more than once makes smt weird? I dont know.

EDIT: IMPORTANT: It did not work! It just saved in one session, when restarting the engine, the same error occurs. The Solution : DONT SAVE TWO SAVEGAMES ON THE SAME SLOT, EVEN IF THE NAME IS DIFFERENT. WHY? WhY Was I looking for this forever?