Set player at as spectator at start of game?

Hello everyone!

I’m having trouble getting the “GetSpectatorPawn()” function to work on my Controller.
I’m guessing this is because my pawn isn’t set up as a spectator when the game starts. I’ve tried grep:ing for

grep -r -i “Spectat” . | awk ‘{print $0,"
"}’ > temp2.txt

both my project and the strategy-sample for a setting that controls this (since doing GetSpectatorPawn() in the StrategyPlayerController is working just fine), but I haven’t found any such setting as of yet. My structure is as far as I know identical as the Strategysample (I have a SpectatorPawn, SpectatorPawnMovement and PlayerController, and they are set up in my GameMode file as such:

AXXGameMode::AXXGameMode(const class FPostConstructInitializeProperties& PCIP)
: Super(PCIP)
{
PlayerControllerClass = AXXPlayerController::StaticClass();
SpectatorClass = AXXSpectatorPawn::StaticClass();
DefaultPawnClass = AXXSpectatorPawn::StaticClass();
GameStateClass = AXXGameState::StaticClass();
}

Calling GetPawn() works fine (I’m getting my pawn back) but GetSpectatorPawn() is returning NULL all the time. Any ideas? Is there any other info that you would need to help me debug this?

/Fredrik

Well, I did some more checking and fiddling around, and it does seem that GetPawn resolves to the same spectator pawn (as expected from the GameMode setup) so I can just Cast<AXXSpectatorPawn>(GetPawn()) to make it work, but it’s not a pretty solution… I would be much happier if I could get GetSpectatorPawn() to work properly instead

Would be glad for any ideas :slight_smile:

/Fredrik

Hi Fredrik,

The reason GetPawn() works and GetSpectatorPawn() works is because they are dependent on the state of the PlayerController: Playing, Spectating, Inactive. Look at the comment for GetSpectatorPawn():


/** Get the Pawn used when spectating. NULL when not spectating. */

So in this case, you are currently in the “playing” state, but the pawn classes happen to be the same for both playing and spectating in your case.

By default the PC starts in the spectator state but immediately changes to playing at the start of the game. If you want to always spectate you can force it by setting it on the PlayerState using bOnlySpectator. Look at the APlayerController::Reset() function to see how that is handled (changes the bIsPlayerWaiting flag, which allows spectators to transition to playing).

This stuff probably warrants some cleanup on our end, but for now hopefully this gets you moving forward!

Thank you Zak!

I had guessed that would be the way, but what was confounding me was more the question of how this works in the strategy game example. Grep:ing in that project doesn’t reveal any usage of the bOnlySpectator variable in the source at all, or as I demonstrated anything containing the substring “Spectat”.
“bOnlySpectator” does seem to be present in a handful of editor pdbs as well as some precompiled headers and obj-files in the intermediate folder however, so I’m guessing it’s somehow set in BP or some other editor-setting in the case of that sample.

On the other hand, the clarification you gave me makes me confident enough to just ignore the mystery of the strategy game example and simply proceed with implementing your suggestion instead.

Cheers and thank you once more!

/edit/
Oh, and if anyone has the same problem and want the correct answer:
Override the APlayerController::Reset() function in your playercontroller like Zak suggested, like so:



void AMyPlayerController::Reset()
{
	Super::Reset();

	PlayerState->bOnlySpectator = true;
}


/edit/

/Fredrik

Today I submitted a couple of fixes with bOnlySpectator, though they mostly apply to networked games. However there was some engine code that was ignoring bOnlySpectator, and that might have caused you some issues.