SetPlayerName bug upgrade from 4.12 to 4.15

Hi,

I just upgraded my engine from 4.12.5 to 4.15 (mainly for compiling improvements).

I have a bug with the PlayerState->SetPlayerName function. It worked well on 4.12 but now I have a random number between 200 and 300 instead.

To help debuging,the function is called from ChoosePlayerStart_Implementation in GameMode.

Thanks for the help !

Is the playerName a random number after you call it? Keep in mind too that the online subsystems will set the player name to associated name of the subsystem, for example the steam subsystem will set it to the steam name of the player.

Hey He-aD,

I’ve tested this in 4.15 and I’m not seeing the same results. On my end, I can SetPlayerName, and then if I log the Player Name I will see the correct name that I’ve just set.

Could you provide me with the code that you’re using so I can take a closer look at your setup? Are you able to reproduce the issue in a clean 4.15 project?

Hi ,

thanks for your reply. I’ll try to reproduce the bug with a clean installation.

Here’s my GameMode code :

AActor* ATopDownGameMode::ChoosePlayerStart_Implementation(AController *Player)
{
	if (Player != nullptr)
	{ 
		AArenaPlayerState* cps = Cast<AArenaPlayerState>(Player->PlayerState);
		AArenaGameState* cgs = Cast<AArenaGameState>(Player->GetWorld()->GetGameState());
		FString PlayerName;
		//ajoute au bon tableau un nouveau joueur
		if (cgs->TTeams[0]->PlayerStates.Num() == cgs->TTeams[1]->PlayerStates.Num()) //ajoute à l'équipe bleu
		{
			cgs->TTeams[0]->PlayerStates.Add(cps);
			PlayerName = FString::FromInt(cgs->TTeams[0]->PlayerStates.Num());
			PlayerName.Append(TEXT("Blue"));
			//cps->Spawn(PlayerName, 0, cgs->TTeams[0]->PlayerStates.Num() - 1, cgs->TTeams[0]->PlayerStates.Num() - 1);
			cps->Spawn(PlayerName, 0, cgs->TTeams[0]->PlayerStates.Num() - 1, 0);
			if (cgs->TTeams[0]->PlayerStates.Num() > MinTeamPlayers) cps->State = EStateEnum::Playing;
			for (TActorIterator<APlayerStart> ActorItr(GetWorld()); ActorItr; ++ActorItr)
			{
				// Same as with the Object Iterator, access the subclass instance with the * or -> operators.
				APlayerStart *Mesh = *ActorItr;
				if (GEngine)
				{
					//GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Blue, FString::SanitizeFloat(cgs->TTeams[0]->PlayerStates[cgs->TTeams[0]->PlayerStates.Num()-1]->GetHealth()));
				}
				if (ActorItr->GetName() == TEXT("SpawnTeamBlue"))
				{ 
					return Mesh;
				}
			}
		}
	}
	return nullptr;
}

SetPlayerName is called in the cps->Spawn function :

void AArenaPlayerState::Spawn(FString Name, int Team, int TeamPosition, uint8 EClass)
{
	SetPlayerName(Name);
	this->Team = Team;
	this->TeamPosition = TeamPosition;
	this->EClass = (EClassEnum)EClass;
}

Thanks for helping.

Hi again ,

I succeed in reproducing the bug with a clean installation. The project is attached (.zip) to this post.

I only have a GameMode class, a character blueprint by default class and a default widget which display the PlayerName.

Here the GameMode code :
// Copyright 1998-2016 Epic Games, Inc. All Rights Reserved.

#include "MyProject.h"
#include "TopDownGameMode.h"
#include "Engine.h"

ATopDownGameMode::ATopDownGameMode()
{
	// set default pawn class to our Blueprinted character
	static ConstructorHelpers::FClassFinder<APawn> PlayerPawnBPClass(TEXT("/Game/NewBlueprint"));
	if (PlayerPawnBPClass.Class != NULL)
	{
		DefaultPawnClass = PlayerPawnBPClass.Class;
	}
}

AActor* ATopDownGameMode::ChoosePlayerStart_Implementation(AController *Player)
{
	if (Player != nullptr)
	{
		for (TActorIterator<APlayerStart> ActorItr(GetWorld()); ActorItr; ++ActorItr)
		{
			// Same as with the Object Iterator, access the subclass instance with the * or -> operators.
			APlayerStart *Mesh = *ActorItr;
			GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Blue, TEXT("Titi"));
			if (ActorItr->GetName() == TEXT("PlayerStart"))
			{ 
				Player->PlayerState->SetPlayerName(TEXT("LALA"));
				GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Blue, Player->PlayerState->PlayerName);
				return Mesh;
			}
		}
	}
	return nullptr;
}

The AddOnScreenDebugMessage display the correct PlayerName but the widget display a number with around 200.

Waiting for your answer.

link text

Thanks for the info. I’ve spent some time testing your project, and I’ve realized that what’s happening is the Player State’s Set Name function is actually being called by default in the player state after you’ve called it in your code, from what I can tell. If you notice, even if you print the player name in your character bp on begin play, it will return a number.

Here’s what I’d recommend: Create your own player state class, override the SetPlayerName function (don’t call the Super) and then call that function from your game mode to set your player name. This will prevent the original implementation of SetPlayerName from overriding the name you chose. Just make sure to set the Player State to the new one you created in your game mode so that it’s using the correct Player State instead of the default one.

Let me know if that works, otherwise we can continue to look for other solutions.

Ok I see what you mean.
Will you change the calling order in future version or stay like it is now ? It’s quite wierd to apply default name after a player has connected to your game.

By the way my game is an online multiplayer. I saw some “net code” in SetPlayerName function. Wouldn’t it cause some problem in multiplayer context if I overwrite it ?

I’ll try what you said and keep you in touch.

It’s possible that it could cause issues, but definitely give it a shot and let me know if that works out for you.

It worked.

I overrided SetPlayerName with an empty function and copy past the original APlayerState function code in my custom Spawn function.

It’s not really elegant hope this will get fixed.

Thanks for your answers.