I’ve been spending the last couple of days trying to work on the load system of my game.
Basically, I need to be sure that GameInstance goes first, if it’s done loading all the info, the Gamemode starts what it needs and only then, when everything is ready, to spawn the character and set it up.
How would you do it?
For now, I just did this:
UFPS_GameInstance::UFPS_GameInstance()
{
CurrentHeath = 100;
}
void UFPS_GameInstance::CreateSaveFile()
{
UFPS_SaveGame* SaveGameData = Cast<UFPS_SaveGame>(UGameplayStatics::CreateSaveGameObject(UFPS_SaveGame::StaticClass()));
UGameplayStatics::SaveGameToSlot(SaveGameData, "Slot01", 0);
}
void UFPS_GameInstance::SaveGame(float HealthCharacter, TArray<FItemData> ItemDataList)
{
UFPS_SaveGame* SaveGameData = Cast<UFPS_SaveGame>(UGameplayStatics::LoadGameFromSlot("Slot01", 0));
if (SaveGameData != nullptr)
{
SaveGameData->HealthToSave = HealthCharacter;
SaveGameData->ItemDataListToSave = ItemDataList;
UGameplayStatics::SaveGameToSlot(SaveGameData, "Slot01", 0);
}
}
void UFPS_GameInstance::LoadGame()
{
UFPS_SaveGame* LoadGameData = Cast<UFPS_SaveGame>(UGameplayStatics::LoadGameFromSlot("Slot01", 0));
if (LoadGameData != nullptr)
{
CurrentHeath = LoadGameData->HealthToSave;
ItemDataListToLoad = LoadGameData->ItemDataListToSave;
OnLoadGameInstanceComplete.Broadcast();
UE_LOG(LogTemp, Warning, TEXT("Second"));
}
else
{
CreateSaveFile();
}
}
AFPS_GameModeBase::AFPS_GameModeBase()
{
PlayerControllerClass = AMyCharacterController::StaticClass();
static ConstructorHelpers::FClassFinder<APawn> PlayerPawnClassFinder(TEXT("/Game/FirstPerson/Blueprints/BP_MyCharacter"));
DefaultPawnClass = nullptr;
GUIManager = CreateDefaultSubobject<UFPS_GUIManager>(TEXT("GUIManager"));
}
void AFPS_GameModeBase::OnLoadGameComplete()
{
if (GetWorld())
{
if (GUIManager)
{
GUIManager->SetupGUIManager();
UE_LOG(LogTemp, Warning, TEXT("Primo"));
SpawnAndPossessCharacter();
}
else
{
UE_LOG(LogTemp, Error, TEXT("GUIManager is nullptr."));
}
}
else
{
UE_LOG(LogTemp, Error, TEXT("GetWorld() returned nullptr."));
}
}
void AFPS_GameModeBase::SpawnAndPossessCharacter()
{
AMyCharacter* NewCharacter = GetWorld()->SpawnActor<AMyCharacter>(DefaultPawnClass, FVector::ZeroVector, FRotator::ZeroRotator);
if (NewCharacter)
{
AMyCharacterController* CurrentController = Cast<AMyCharacterController>(UGameplayStatics::GetPlayerController(GetWorld(), 0));
if (CurrentController)
{
CurrentController->Possess(NewCharacter);
UE_LOG(LogTemp, Warning, TEXT("Doppio"));
}
else
{
APlayerController* NewPlayerController = UGameplayStatics::GetPlayerController(GetWorld(), 0);
if (NewPlayerController)
{
NewPlayerController->Possess(NewCharacter);
UE_LOG(LogTemp, Warning, TEXT("Doppio"));
UE_LOG(LogTemp, Warning, TEXT("New player controller spawned and character possessed."));
}
else
{
UE_LOG(LogTemp, Error, TEXT("Failed to get or spawn a player controller."));
}
}
}
else
{
UE_LOG(LogTemp, Error, TEXT("Failed to spawn player character."));
}
}
void AFPS_GameModeBase::PostInitializeComponents()
{
Super::PostInitializeComponents();
// Attempt to bind to the OnLoadGameInstanceComplete event
if (UFPS_GameInstance* GameInstance = Cast<UFPS_GameInstance>(GetGameInstance()))
{
GameInstance->OnLoadGameInstanceComplete.AddDynamic(this, &AFPS_GameModeBase::OnLoadGameComplete);
GameInstance->LoadGame();
}
}
I tried to call the Load in the Init of the GameInstance, but for some reason, it seems the Load doesn’t get called in there. It calls it successfully only if I do it in the GameMode.
As it is, it seems to be working (key word: seems) but it spawns 2 characters + an AI controller and I don’t understand why…
Do you have any resource material you could recommend?