PlayerState always NULL, weapons per Team ShooterGame

Hi, i’m new in ue4 and looks a very good engine (with a very good dev tools!)

My problem:

I want to give team1 weapons and for the other team give nothing, so i tested this:


void AShooterCharacter::PostInitializeComponents()
 {
     Super::PostInitializeComponents();
 
     // etc...
 
     if (Role == ROLE_Authority)
     {
         Health = GetMaxHealth();
 
         if (PlayerState != NULL) {
             AShooterPlayerState* MyPlayerState = Cast<AShooterPlayerState>(PlayerState);
             if (MyPlayerState != NULL)
             {
                 if (MyPlayerState->GetTeamNum() == 1)
                 {
                     SpawnDefaultInventory();
                 }
             }
         }
     }
 }

the problem is that PlayerState is always null and i got no weapons for all teams, someone can help me with that?,

Also i dont really understand the client/server/shared coded in ue4, in source sdk are split into folders and with if/defs so i can understand very fast what code is executed…

Well… looks like no one knows,

I temporally fixed this by using AShooterCharacter::Tick function with a boolean so when i give the weapons i set CharacterEquiped = true, and when i remove the weapons (player die) i set CharacterEquiped = false



void AShooterCharacter::Tick(float DeltaSeconds)
{
	Super::Tick(DeltaSeconds);

	if (CharacterEquiped == false && PlayerState != NULL)
	{
		// check stuff, give weapons..
		CharacterEquiped = true;
	}

	// ..
}



If anyone know a better function that is called when player spawns and when PlayerState is not NULL tell me so i can remove this ugly code from the tick function…

APawn::PossessedBy is when player state if set to the pawn, as far as i am aware after looking for a moment, so sometime after that you can access it and it should not be null, so you can at least start from there. You could more then likely use BeginPlay if i had to guess and have it work there.

Yes, PossessedBy is working fine :slight_smile:

Thank you

The bots dont use PossesedBy so i need to make a workaround for bots… (only happends with first spawn, after killing bot and spawns again works fine…)

BeginPlay may work better then, but as i said i am not sure, i have not looked much into playerstates yet

BeginPlay is called when the player begin play (when connected to server and start playing)

Also looks like shooterGame sometimes crash:


UE_LOG(LogShooter, Log, TEXT("InitBot: %s spawned on %s"), *Bot->GetName(), *BestStart->GetName());

sometimes (every 50 tests for example) GetName crash trying to read Name field (null i think), i changed a bit the code and hoping dont crash anymore, my working code is…

ShooterGame_TeamDeathMatch.cpp



void AShooterGame_TeamDeathMatch::InitBot(AShooterBot* Bot, int BotNumber)
{
	// Setup bot name / teleport to spawn position
	Super::InitBot(Bot, BotNumber);
}


ShooterGameMode.cpp



void AShooterGameMode::InitBot(AShooterBot* Bot, int BotNumber)
{
	AShooterAIController* AIPC = Bot ? Cast<AShooterAIController>(Bot->GetController()) : NULL;
	if (AIPC)
	{
		AShooterPlayerState* BotPlayerState = CastChecked<AShooterPlayerState>(AIPC->PlayerState);
		if (BotPlayerState)
		{
			AActor* BestStart = ChoosePlayerStart(AIPC);

			// set bot name
			FString BotName = FString::Printf(TEXT("Bot %d"), BotNumber);
			BotPlayerState->PlayerName = BotName;

			// set team number
			const int32 TeamNum =/* ChooseTeam(BotPlayerState)*/1;
			BotPlayerState->SetTeamNum(TeamNum);

			// setup initial spawn position
			Bot->TeleportTo(BestStart->GetActorLocation(), BestStart->GetActorRotation(), false, true);

			// setup stuff
			Bot->SetupCharacterStuff();

			UE_LOG(LogShooter, Log, TEXT("InitBot: %s spawned on %s"), *Bot->GetName(), *BestStart->GetName());
		}
		else
		{
			UE_LOG(LogShooter, Error, TEXT("InitBot: PlayerState-NULL"));
		}
	}
}

ShooterCharacter.cpp



void AShooterCharacter::PossessedBy(class AController* InController)
{
	Super::PossessedBy(InController);

	// [server] as soon as PlayerState is assigned, set team colors of this pawn for local player
	UpdateTeamColorsAllMIDs();

	SetupCharacterStuff();
}

void AShooterCharacter::SetupCharacterStuff()
{
	if (PlayerState != NULL)
	{
		AShooterPlayerState* MyPlayerState = Cast<AShooterPlayerState>(PlayerState);
		if (MyPlayerState != NULL)
		{
			TeamNum = MyPlayerState->GetTeamNum();

			if (TeamNum != -1)
			{
				Health = GetMaxHealth();

				if (TeamNum == 0)
				{
					//...
				}
				else
				{
					//..
				}
			}
		}
	}
}


Looks like all is working fine for now, i hope the crash is fixed too.