Where are instances of Default PlayerControllers and Pawns created in GameMode?

Hello,

I’d like to control the spawning of the default PlayerControllers and Pawns that I’m setting in the GameMode constructor but I don’t know which function would be optimal to override. The reason is that I want to do further setup on the one instance of Controller and Pawn I make. Is there a specific function that I should look into?

I’d like to hook into the processes where those are getting spawned. Basically, looking for where something like this is called, (Note: don’t know what it would look like but something like this)

playerController = NewDefaultPlayerController()

playerController->setPawn( NewDefaultPawn() )

note: can’t seem to make template brackets.

Do you want to change the default classes or do you want to hook into the processes where those are getting spawned?

Hooking into the spawning process of a PlayerController

To hook into the process when the GameMode spawns you PlayerController you can override the following method in which the GameMode does the actual spawning:

/** 
 * Spawns a PlayerController at the specified location; split out from Login()/HandleSeamlessTravelPlayer() for easier overriding 
 *
 * @param RemoteRole the role this controller will play remotely
 * @param SpawnLocation location in the world to spawn
 * @param SpawnRotation rotation to set relative to the world
 *
 * @return PlayerController for the player, NULL if there is any reason this player shouldn't exist or due to some error
 */
virtual APlayerController* SpawnPlayerController(ENetRole InRemoteRole, FVector const& SpawnLocation, FRotator const& SpawnRotation);

You can also override the following which will get called just after the GameMode has spawned a new PlayerController or after a SeamlessTravel (I recommend hooking your logic into the next function):

/**
 * handles all player initialization that is shared between the travel methods
 * (i.e. called from both PostLogin() and HandleSeamlessTravelPlayer())
 */
virtual void GenericPlayerInitialization(AController* C);

Hooking into the spawning process of your Pawn aka Character

The spawning process will try to spawn a Pawn aka Character at a given PlayerStart, you will be able to modify the final class implementing the following BlueprintNativeEvent.

/** returns default pawn class for given controller */
UFUNCTION(BlueprintNativeEvent, Category="Game")
UClass* GetDefaultPawnClassForController(AController* InController);

To override the base event just add the following to your header class and add the implementation into your cpp, remember to call the Super.

virtual UClass* GetDefaultPawnClassForController_Implementation(AController* InController) override;

And to control the actual spawning process you have to implement the following BlueprintNativeEvent (just add the implementation but not the declaration into your header):

/**
 * @param	NewPlayer - Controller for whom this pawn is spawned
 * @param	StartSpot - PlayerStart at which to spawn pawn
 * @return	a pawn of the default pawn class
 */
UFUNCTION(BlueprintNativeEvent, Category="Game")
APawn* SpawnDefaultPawnFor(AController* NewPlayer, class AActor* StartSpot);

To override the base event just add the following to your header class and add the implementation into your cpp, remember to call the Super.

virtual APawn* SpawnDefaultPawnFor_ImplementationAController* NewPlayer, class AActor* StartSpot) override;

You should be good to got with those hooks.

Thanks so much. I really appreciate the answer and the speed :slight_smile:

If it works for you remember to accept the answer ^^

Actually, after reading a bit more, I understand that SpawnDefaultPawnFor needs to be “implemented”, like you said but it’s never called. My controller function is called but my SpawnDefaultPawnFor_Implementation is never called. Any ideas would be much appreciated.

That’s strange, I’ll prepare a test once I’m back home.

Ok, I missed a small thing when overriding BlueprintNativeEvents, you have to declare the override of your implementation in your header. I’ll update the answer according ^^.

So that is what I did, but it doesn’t seem to be called. I wrote the implementation function as an override in the header and defined it in the cpp but when I step through the editor at runtime, the SpawnPlayerController function is called but my breakpoint in the SpawnDefaultPawnFor_Implementation is skipped completely.

Might it be that your BP is not calling the parent function?

Very well could be. The only way this function is called is through blueprints?

In the c++, I call the super method inside the “implementation” like so…

APawn* ALexusGameMode::SpawnDefaultPawnFor_Implementation( AController* NewPlayer, AActor* StartSpot )
{
	auto pawn = Cast<AnotherPawn>( Super::SpawnDefaultPawnFor( NewPlayer, StartSpot ) );
        // further setup here.
	return pawn;
}

No but the call hierarchy is between C++ and BP, so if you do not call the parent/super method you will break the chain somewhere.

And you do not have any BP that implements that function?