Hi, I’m working on my first multiplayer game and am having trouble initializing the game, specifically drawing the HUD. My debugging has really hit a dead end and I’m not knowledgeable enough to know what could be wrong. Here’s what I’m trying to do:
My gamemode class, AMatch_GameModeBase has these two functions in its header file (along with some other stuff obviously):
// AMatch_GameModeBase.h
private:
// Called when a player successfully logs into the game.
virtual void PostLogin(APlayerController* NewPlayer) override;
// Sets up the game state, player pawns, and player controllers.
void SetUpMatch();
// An array of all connected player controllers.
TArray<AMatch_PlayerController*> ConnectedPlayerControllers;
In the implementation file, I want to add the player controller of new players to an array when they log in. Then, if there are two players logged in (it’s a 2-player game), I want to set up the match, which calls setup functions in the game state, player pawn, and player controller classes.
// AMatch_GameModeBase.cpp
void AMatch_GameModeBase::PostLogin(APlayerController* NewPlayer)
{
Super::PostLogin(NewPlayer);
// If the connected player is has a match player controller...
if (Cast<AMatch_PlayerController>(NewPlayer))
{
// Add that controller to the controller array
ConnectedPlayerControllers.Add(Cast<AMatch_PlayerController>(NewPlayer));
}
// If two players have connected...
if (ConnectedPlayerControllers.Num() == 2)
{
// Set up the match.
SetUpMatch();
}
}
void AMatch_GameModeBase::SetUpMatch()
{
// Get a pointer to the game state.
MatchGameState = Cast<AMatch_GameStateBase>(GetWorld()->GetGameState());
// Begin the match.
if (MatchGameState)
{
// Begin the first player's turn.
MatchGameState->BeginMatch();
}
// Initialize both player pawns.
Cast<AMatch_PlayerPawn>(ConnectedPlayerControllers[0]->GetPawn())->InitializePlayerPawn(0);
Cast<AMatch_PlayerPawn>(ConnectedPlayerControllers[1]->GetPawn())->InitializePlayerPawn(1);
// Initialize both player controllers.
Cast<AMatch_PlayerController>(ConnectedPlayerControllers[0])->InitializePlayerController(0);
Cast<AMatch_PlayerController>(ConnectedPlayerControllers[1])->InitializePlayerController(1);
}
The only thing that InitializePlayerController() does is set a local variable to the integer parameter. The problem I’m having is in the player pawn.
// AMatch_PlayerPawn.h
public:
// Initializes values and sets up the HUD for this player once they connect.
void InitializePlayerPawn(int PassedPlayerIndex);
// Index used to differentiate players.
UPROPERTY()
int PlayerIndex;
This function should set the player index variable and call two functions from this player’s pawn’s controller’s HUD (that’s a mouthful):
// AMatch_PlayerPawn.cpp
void AMatch_PlayerPawn::InitializePlayerPawn(int PassedPlayerIndex)
{
// Set the player index for this pawn.
PlayerIndex = PassedPlayerIndex;
// Get this pawn's controller.
AMatch_PlayerController* PlayerController = Cast<AMatch_PlayerController>(UGameplayStatics::GetPlayerController(this, PlayerIndex));
// If this pawn's player controller was found...
if (PlayerController)
{
// Get this pawn's controller's HUD.
AMatch_HUD* Match_HUD = Cast<AMatch_HUD>(PlayerController->GetHUD());
if (Match_HUD)
{
// Create the base widget.
Match_HUD->CreateBaseWidget(PlayerIndex);
// Update the displayed name of this map.
Match_HUD->UpdateMapNameHUD("Clockwork");
}
}
}
I think that this is where the problem is. When adding debug messages around the if (Match_HUD) line, it says that it returns false.
I’d really appreciate anyone’s help. I’ve tried everything I can think of: using BeginPlay(), using the Tick function to retry every frame, making them client, server, or multicast functions, but nothing has worked. I’m really stumped.
Thanks in advance!