C++ Saving Player Information in Game Instance - Multiplayer Game

Ok so I spent the last two days and about 15+ hours trying to figure this out, and now that I finally have I wanted to share with everyone how I got my problem solved.

First off I want to describe my game and the initial problem. The game is a multiplayer first person shooter, and when a match ends, the players get sent to a new level. In this level is just a basic widget (for now) so that the team that won the last round can vote on which level to go to next (Eventually depending on which levels you “Own your team will get benefits”). Ok so what I was trying to do is save which team the player was on between levels, and which team won the previous match so that the widget loaded only for the winning team. The problem I was having is that the playerController used in the Vote level is different from that used in the maps that the player has a pawn to control. Even though the PlayerState was the same, and according to Unreal’s documentation the PlayerState is supposed to persist during seamless travel when using Relative travel the player team information wasn’t staying. So I looked to save this information in the GameInstance. Well the problem was is it would only save the information on the “Server” player.

Now for the solution. In order to get this to work I had to write a UFUNTION in my PlayerController class that would be called on the client side to save the information I wanted to that clients GameInstance Below is some code bits from my project that hopefully helps someone out with a problem like this. The reason I needed the extra function is so that the server could tell the clients “hey save this information on your side”

in the ABasePlayerController.h file





//ABasePlayerController.h this is our custom PlayerController class

UFUNTION(Client, Reliable)
void ClientOnMatchEnd(ETeamEnum *WinnerTeam);

//ABasePlayerController.cpp

void ABasePlayerController::ClientOnMatchEnd_Implementation(ETeamEnum *WinnerTeam)
{
//UBaseGameInstance is our custom GameInstance class

UBaseGameInstance * BaseGameInstance = Cast<UbaseGameInstance>(GetGameInstane());
if(BaseGameInstance)
{
[INDENT]BaseGameInstance->PlayerPreviousTeam = GetTeam();
BaseGameInstance->MatchWinner = WinnerTeam;

}
[/INDENT]

//ABaseGameMode.cpp is our custom game mode that the rest of our game modes inherit from

void ABaseGameMode::EndMatch(ETeamEnum *WinnerTeam)
{

if(IsMatchInProgress())
{
[INDENT]ABaseGameState * BaseGameState = Cast<ABaseGameState>(GameState);
if(BaseGameState)
{
[INDENT]BaseGameState->MatchWinner = WinnerTeam;

//Here I'm getting the PlayerControllerIterator so I can tell all PlayerControllers connected to the game to run the ClientOnMatchEnd funtion
for(FConstPlayerControllerIterator PlayerItr = GetWorld()->GetPlayerControllerIterator(); PlayerItr; ++PlayerItr)
{
[INDENT]ABasePlayerController * PC = Cast<ABasePlayerController>(*PlayerItr);
if(PC)
{
[INDENT]PC->ClientOnMatchEnd(WinnerTeam);
}[/INDENT]
}[/INDENT]
}[/INDENT]
}[/INDENT]
}



When ClientOnMatchEnd is called within BaseGameMode::EndMatch() is will actually call the ClientOnMatchEnd_Implementation function on each of the clients connected to the server. So when dealing with games played over servers, and if you want information to be sent to the clients GameInstance, you must create a Client function that gets called on all the clients. When I declared the UFUNCTION I had the two parameters (Client, Reliable) the first Client basically means that this function will only run on the client side, not the server side, Reliable means that it will be prioritised if the servers network is bogged down. Hopefully this helps someone out on getting information to save to their GameInstance on a multiplayer game.