Perhaps someone can assist me with this, since this is proving to be a complete nightmare.
Our game is designed to work as part of an installation, with three PC’s and 20 Android tablets. Each one of these has a text file on it which configures it for the type of player it is. Android tablets are supposed to spawn into the game world as one type of pawn, whereas the PC’s are supposed to spawn in the world as a different type of pawn. I’ve been overriding a Gamemode function called “GetDefaultPawnClassForController”, which looks like it’s supposed to allow the end user to spawn a pawn for a player based on the Player Controller. By default, this function just returns the GameMode’s default Pawn, so I don’t understand why they would allow us to pass in a Controller if it wasn’t intended to be used this way.
After following this tutorial on the Wiki however I can confirm that it absolutely doesn’t work for Network games, because the pawn to spawn gets to the Server too late or whatever.
In order to determine which Pawn to spawn, the PlayerController reads from a text file to figure out which type of player it is (Tablet or Screen), and attempts to set a variable with the correct pawn class to spawn. Unfortunately it doesn’t seem to work at all. It seems to set the Default Pawn class for ALL player controllers, not the specific client controller.
Here’s the code, perhaps someone can make sense of it all. I’ve even tried calling ‘RestartPlayer’ on the PlayerController, but still not having any luck with it - It’s always reading which pawn to be from the Server.
GESGame_PlayerController.cpp
// Stormtide 2015
#include "GESGame.h"
#include "GESGame_PlayerController.h"
AGESGame_PlayerController::AGESGame_PlayerController(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer)
{
GESServerPawn = NULL;
GESClientPawn = NULL;
MyPawnClass = NULL;
bReplicates = true;
GESCheckString = FString(TEXT("Tablet")); // Players are Tablets By Default
}
void AGESGame_PlayerController::PostInitializeComponents()
{
Super::PostInitializeComponents();
if (GetWorld())
{
DeterminePawnClass();
}
}
void AGESGame_PlayerController::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
{
DOREPLIFETIME(AGESGame_PlayerController, MyPawnClass);
}
UClass* AGESGame_PlayerController::GetGESPawnClass()
{
return MyPawnClass;
}
void AGESGame_PlayerController::DeterminePawnClass()
{
if (IsLocalController())
{
ASSERTV(GESClientPawn != NULL, *FString::Printf(TEXT("Player Controller: No Client Pawn Class Specified - Aborting")));
ASSERTV(GESServerPawn != NULL, *FString::Printf(TEXT("Player Controller: No Server Pawn Class Specified - Aborting")));
/* Load Text File Into String Array */
TArray<FString> TextStrings;
const FString FilePath = FPaths::GameDir() + "Textfiles/GESSettings.txt";
/* Check if we successfully loaded the string */
bool bDone = FFileHelper::LoadANSITextFileToStrings(*FilePath, NULL, TextStrings);
ASSERTV(bDone, NULL, *FString::Printf(TEXT("Player Controller: Couldn't load GESSettings.txt - Aborting")));
GESCheckString = TextStrings[0];
if (GESCheckString == "Screen")
{
ServerSetPawn(GESServerPawn);
}
else if (GESCheckString == "Tablet")
{
ServerSetPawn(GESClientPawn);
}
}
}
bool AGESGame_PlayerController::ServerSetPawn_Validate(TSubclassOf<APawn> InPawnClass)
{
return true;
}
void AGESGame_PlayerController::ServerSetPawn_Implementation(TSubclassOf<APawn> InPawnClass)
{
MyPawnClass = InPawnClass;
/* Restart Player */
GetWorld()->GetAuthGameMode()->RestartPlayer(this);
GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Yellow, FString::Printf(TEXT("Name = %s"), *MyPawnClass->GetDefaultObject()->GetName()));
}
GESGame_DefaultGameMode.cpp
UClass* AGESGame_DefaultGameMode::GetDefaultPawnClassForController(AController* InController)
{
/* Override Functionality to get Pawn from PlayerController */
AGESGame_PlayerController* GESController = Cast<AGESGame_PlayerController>(InController);
if (GESController)
{
return GESController->GetGESPawnClass();;
}
return DefaultPawnClass;
}