Only one PlayerController gets spawned in Multiplayer

Hello dear community,

I am developing a little racing game with multiplayer capabilites in UE4.12. However, I noticed that, whenever I start it in the editor with more than one player, only one PlayerController is spawned, although 2 pawns are created. I can control them both, once I swap the viewport. How do I configure the game, so that for each Player that logged in, a PlayerController gets spawned? I already digged into the GameMode.cpp but it look all fine to me. Can somebody please explain this behavior and/or post a solution?

Here is the content of my ARacingGameMode.cpp:

// Copyright 1998-2016 Epic Games, Inc. All Rights Reserved.

#include "RacingGame.h"
#include "RacingGameGameMode.h"
#include "RacingGamePawn.h"
#include "RacingGameGameState.h"
#include "RacingGameHud.h"
#include "GameFramework/GameNetworkManager.h"
#include "Matinee/MatineeActor.h"

void ARacingGameGameMode::Tick(float deltaSeconds)
{
	Super::Tick(deltaSeconds);
	if (m_CalcBuffer > 0) {
		m_CalcBuffer -= deltaSeconds;
	}
	else{
	CalculatePlayerPositions();
	}
	


}

void ARacingGameGameMode::EndMatch()
{
	Super::EndMatch();
	UE_LOG(LogTemp, Warning, TEXT("Match has ended."));


}



ARacingGameGameMode::ARacingGameGameMode() {
	PlayerControllerClass = ARacingGamePlayerController::StaticClass();
	GameStateClass = ARacingGameGameState::StaticClass();
	PlayerStateClass = ARacingGamePlayerState::StaticClass();
	DefaultPawnClass = ARacingGamePawn::StaticClass();

	static ConstructorHelpers::FClassFinder <AHUD> MyDefaultHUD(TEXT("/Game/RacingGameContent/HUD/BP_RacingGameHud"));
	HUDClass = (UClass*)MyDefaultHUD.Class;
	this->bStartPlayersAsSpectators = false;
	bDelayedStart = false;
	m_MapCheckPoints = TArray<AActor*>();
	m_SpawnPoints = TArray<AActor*>();

}


void ARacingGameGameMode::PostLogin(APlayerController* NewPlayer)
{
	Super::PostLogin(NewPlayer);
	m_PlayerControllers.Add(Cast<ARacingGamePlayerController>(NewPlayer));
	Cast<ARacingGamePlayerState>(NewPlayer->PlayerState)->m_LastCheckpointPosition = m_MapCheckPoints[0]->GetActorLocation();
	Cast<ARacingGamePlayerState>(NewPlayer->PlayerState)->m_LastCheckpointRotation = m_MapCheckPoints[0]->GetActorRotation();
	
}

void ARacingGameGameMode::CalculatePlayerPositions()
{
	
	m_PlayerControllers.Sort([](const ARacingGamePlayerController& A, const ARacingGamePlayerController& B) {
		
		ARacingGamePlayerState* _StateA = Cast<ARacingGamePlayerState>(A.PlayerState);
		ARacingGamePlayerState* _StateB = Cast<ARacingGamePlayerState>(B.PlayerState);
		ARacingGamePawn* _pawnA = Cast<ARacingGamePawn>(A.GetPawn());
		ARacingGamePawn* _pawnB = Cast<ARacingGamePawn>(B.GetPawn());
		




		if (A.CalcPositionScore() == B.CalcPositionScore())
		{
			FVector _distA = _StateA->m_LastCheckpointPosition - _pawnA->GetActorLocation();
			FVector _distB = _StateB->m_LastCheckpointPosition - _pawnB->GetActorLocation();
			if (_distA.Size() > _distB.Size())
			{
				return true;
			}
			else if (_distA.Size() < _distB.Size())
			{
				return false;
			}

		}

		if (A.CalcPositionScore() > B.CalcPositionScore()) {
			return true;
		}

		else {

			return false;
		}
	});
	
	uint8 _index = 0;
	for (ARacingGamePlayerController* _controller : m_PlayerControllers) {

		Cast<ARacingGamePlayerState>(_controller->PlayerState)->m_PlayerPosition = _index+1;
		_index++;
	}



}

void ARacingGameGameMode::PreInitializeComponents()
{
	Super::PreInitializeComponents();

	FActorSpawnParameters SpawnInfo;
	SpawnInfo.Instigator = Instigator;
	SpawnInfo.ObjectFlags |= RF_Transient;	// We never want to save game states or network managers into a map

											// Fallback to default GameState if none was specified.
	if (GameStateClass == NULL)
	{
		//UE_LOG(LogGameMode, Warning, TEXT("No GameStateClass was specified in %s (%s)"), *GetName(), *GetClass()->GetName());
		GameStateClass = ARacingGameGameState::StaticClass();
	}

	GameState = ()->SpawnActor<ARacingGameGameState>(GameStateClass, SpawnInfo);
	()->GameState = GameState;
	if (GameState)
	{
		GameState->AuthorityGameMode = this;
	}

	// Only need NetworkManager for servers in net games
	()->NetworkManager = GetWorldSettings()->GameNetworkManagerClass ? ()->SpawnActor<AGameNetworkManager>(GetWorldSettings()->GameNetworkManagerClass, SpawnInfo) : NULL;

	InitGameState();
}


void ARacingGameGameMode::InitGame(const FString& MapName, const FString& Options, FString& ErrorMessage)
{
	UWorld* World = ();
	
	// save Options for future use
	OptionsString = Options;

	UClass* const SessionClass = GetGameSessionClass();
	FActorSpawnParameters SpawnInfo;
	SpawnInfo.Instigator = Instigator;
	SpawnInfo.ObjectFlags |= RF_Transient;	// We never want to save game sessions into a map
	GameSession = World->SpawnActor<AGameSession>(SessionClass, SpawnInfo);
	GameSession->InitOptions(Options);
	GameSession->MaxPlayers = 2;

	


	if (GetNetMode() != NM_Standalone)
	{
		FOnlineSessionSettings* SessionSettings = NULL;
		IOnlineSessionPtr SessionInt = Online::GetSessionInterface(World);
		if (SessionInt.IsValid())
		{
			SessionSettings = SessionInt->GetSessionSettings(GameSession->SessionName);
		}

		// Attempt to login, returning true means an async login is in flight
		if (!SessionSettings && !GameSession->ProcessAutoLogin())
		{
			GameSession->RegisterServer();
		}
	}

	for (TActorIterator<APlayerStart> ActorItr(()); ActorItr; ++ActorItr)
	{
		// Same as with the Object Iterator, access the subclass instance with the * or -> operators.
		m_SpawnPoints.Add(*ActorItr);
	}
	
	for (TActorIterator<ARacingGameCheckpoint> ActorItr(()); ActorItr; ++ActorItr)
	{
		// Same as with the Object Iterator, access the subclass instance with the * or -> operators.
		m_MapCheckPoints.Add(*ActorItr);
	}


	SetMatchState(MatchState::EnteringMap);
}

AActor* ARacingGameGameMode::ChoosePlayerStart_Implementation(AController* Player)
{
	UE_LOG(LogTemp, Warning, TEXT("Choose player start executed."))
		// Choose a player start
		APlayerStart* FoundPlayerStart = NULL;
	ARacingGamePlayerController*  _PlayerController = Cast<ARacingGamePlayerController>(Player);
	UClass* PawnClass = GetDefaultPawnClassForController(_PlayerController);
	AActor* SpawnPoint = m_SpawnPoints[0];
	m_SpawnPoints.RemoveAt(0);
	return SpawnPoint;


}

void ARacingGameGameMode::StartMatch()
{
	if (HasMatchStarted())
	{
		// Already started
		return;
	}



	//Let the game session override the StartMatch function, in case it wants to wait for arbitration
	if (GameSession->HandleStartMatchRequest())
	{
		UE_LOG(LogTemp, Warning, TEXT("MatchStartHandleRequest has been executed."));
		return;
	}
	UE_LOG(LogTemp, Warning, TEXT("Internal MatchState set to InProgress. (Starting Match)"));
	Cast<ARacingGameGameState>(GameState)->m_MaxPlayers = GameSession->MaxPlayers;
	Cast<ARacingGameGameState>(GameState)->m_MaxLaps = m_maxLaps;
	Cast<ARacingGameGameState>(GameState)->m_NumCheckPoints = m_MapCheckPoints.Num();
	SetMatchState(MatchState::InProgress);
}

bool ARacingGameGameMode::ReadyToStartMatch_Implementation()
{
	UE_LOG(LogTemp, Warning, TEXT("Game session size %s"), *FString::FromInt(GameSession->MaxPlayers))

		// If bDelayed Start is set, wait for a manual match start
		if (bDelayedStart)
		{
			return false;
		}

	// By default start when we have > 0 players
	if (GetMatchState() == MatchState::WaitingToStart)
	{
		if (NumPlayers + NumBots == GameSession->MaxPlayers)
		{
			return true;
		}
	}
	return false;
}

It should spawn out of the box, maybe PostLogin is not called? Also to be sure check if in logs something shows up, go Window->Developer Tools->Output Log.

Hello , and thank you for your quick response. Post Login gets called as expected, the Log doesn’t show anything suspicious as well :(.

Did this issue ever get resolved? I am seeing the same thing with multiplayer in the Editor - One PlayerController and multiple Characters.

I have the same problem and I can’t figure out why.
Did you find it ?