How to check which Begin Play (or something similar) goes first - c++

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?

As long as you aren’t doing anything asynchronously, this should just work out. The game instance is fully created before the world, the world before the game mode, and the game mode before all actors.

Here’s a chart that may more clearly visualize it:


Of course the begin play in UWorld is the UWorld’s begin play, not begin play for all actors

But if I want to start an action in the Init of the Game Instance, how do I make the GameMode listen to it?

You can’t. At the point of game instance Init, gamemode hasn’t even been created yet.

image

If you share what the action is and why it needs to be in game instance, I might be able to help you come up with something more specific.

There is an EXTREMELY jank way if you really need to do something with game mode in game instance, but it’s probably best that you share what you want first.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.