Download

PlayerControllers not posessing pawns

Hello all,

I’ve got a co-op 2D side-scroller im making and im running into an issue with the player controllers not posessing their pawns on startup.

2 of the clients connect just fine and everything works perfectly for them. However, Client 1 and the server, every time, never got posession of their pawns. The game spawns them for them, but they never get control, camera, nothing.

All 4 characters are the same class, just different animations setup. The only code I’ve overwritten is the GetDefaultPawnClassForPlayer(AController* InController) function. havent touched any other spawn code or controller code.

.cpp


 // Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.

#include "SideOp.h"
#include "SideOpGameMode.h"
#include "SideOpCharacter.h"

ASideOpGameMode::ASideOpGameMode(const FObjectInitializer& ObjectInitializer)
	: Super(ObjectInitializer)
{
	static ConstructorHelpers::FClassFinder<APawn> PlayerDefaultPawnObject(TEXT("Pawn'/Game/Blueprints/BP_Character.BP_Character_C'"));
	static ConstructorHelpers::FClassFinder<APawn> BluePlayerObject(TEXT("Pawn'/Game/Players/BP_Character_Blue.BP_Character_Blue_C'"));
	static ConstructorHelpers::FClassFinder<APawn> BeigePlayerObject(TEXT("Pawn'/Game/Players/BP_Character_Beige.BP_Character_Beige_C'"));
	static ConstructorHelpers::FClassFinder<APawn> GreenPlayerObject(TEXT("Pawn'/Game/Players/BP_Character_Green.BP_Character_Green_C'"));
	static ConstructorHelpers::FClassFinder<APawn> YellowPlayerObject(TEXT("Pawn'/Game/Players/BP_Character_Yellow.BP_Character_Yellow_C'"));
	static ConstructorHelpers::FClassFinder<APawn> PinkPlayerObject(TEXT("Pawn'/Game/Players/BP_Character_Pink.BP_Character_Pink_C'"));

	// set default pawn class to our default character
	if (PlayerDefaultPawnObject.Class != NULL /*&& HUDObject.Class != NULL*/)
	{
		DefaultPawnClass = PlayerDefaultPawnObject.Class; 

	}

	// Set the rest of the characters
	if (BluePlayerObject.Class != NULL)
	{
		BluePlayer = BluePlayerObject.Class;
		UE_LOG(LogTemp, Warning, TEXT("Blue Pawn Set"));
	}

	if (BeigePlayerObject.Class != NULL)
	{
		BeigePlayer = BeigePlayerObject.Class;
		UE_LOG(LogTemp, Warning, TEXT("Beige Pawn Set"));
	}

	if (GreenPlayerObject.Class != NULL)
	{
		GreenPlayer = GreenPlayerObject.Class;
		UE_LOG(LogTemp, Warning, TEXT("Green Pawn Set"));
	}

	if (YellowPlayerObject.Class != NULL)
	{
		YellowPlayer = YellowPlayerObject.Class;
		UE_LOG(LogTemp, Warning, TEXT("Yellow Pawn Set"));
	}

	if (PinkPlayerObject.Class != NULL)
	{
		PinkPlayer = PinkPlayerObject.Class;
		UE_LOG(LogTemp, Warning, TEXT("Pink Pawn Set"));
	}

}

void ASideOpGameMode::BeginPlay()
{
	Super::BeginPlay();
	InitialID = GetWorld()->GetGameState()->PlayerArray[0]->PlayerId;
}



UClass* ASideOpGameMode::GetDefaultPawnClassForController(AController* InController)
{
	Super::GetDefaultPawnClassForController(InController);
	APlayerController* PC = InController->CastToPlayerController();
	int32 PlayerID = PC->PlayerState->PlayerId;

	UE_LOG(LogTemp, Warning, TEXT("Player ID is: %d"), PlayerID);


	if (PlayerID == InitialID)
	{
		if (BluePlayer)
		{
			UE_LOG(LogTemp, Warning, TEXT("Using Blue Player"));
			return BluePlayer;

		}
		else
		{
			UE_LOG(LogTemp, Warning, TEXT("Using the default Player"));
			return DefaultPawnClass;
		}
	}
	else if (PlayerID == (InitialID + 1))
	{
		if (BeigePlayer)
		{
			UE_LOG(LogTemp, Warning, TEXT("Using Beige Player"));
			return BeigePlayer;

		}
		else
		{
			UE_LOG(LogTemp, Warning, TEXT("Using the default Player"));
			return DefaultPawnClass;
		}
	}
	else if (PlayerID == (InitialID + 2))
	{
		if (GreenPlayer)
		{
			return GreenPlayer;
			UE_LOG(LogTemp, Warning, TEXT("Using Green Player"));
		}
		else
		{
			UE_LOG(LogTemp, Warning, TEXT("Using the default Player"));
			return DefaultPawnClass;
		}
	}
	else if (PlayerID == (InitialID + 3))
	{
		if (YellowPlayer)
		{
			return YellowPlayer;
			UE_LOG(LogTemp, Warning, TEXT("Using Yellow Player"));
		}
		else
		{
			UE_LOG(LogTemp, Warning, TEXT("Using the default Player"));
			return DefaultPawnClass;
		}
	}
	else if (PlayerID == (InitialID + 4))
	{
		if (PinkPlayer)
		{
			return PinkPlayer;
			UE_LOG(LogTemp, Warning, TEXT("Using Pink Player"));
		}
		else
		{
			UE_LOG(LogTemp, Warning, TEXT("Using the default Player"));
			return DefaultPawnClass;
		}
	}
	else
	{

		UE_LOG(LogTemp, Warning, TEXT("We're using the default :/"));
		return DefaultPawnClass;
	}
}

.h


// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.

#pragma once
#include "GameFramework/GameMode.h"
#include "SideOpGameMode.generated.h"

// The GameMode defines the game being played. It governs the game rules, scoring, what actors
// are allowed to exist in this game type, and who may enter the game.
//
// This game mode just sets the default pawn to be the MyCharacter asset, which is a subclass of SideOpCharacter

UCLASS(minimalapi)
class ASideOpGameMode : public AGameMode
{
	GENERATED_BODY()


public:
	ASideOpGameMode(const FObjectInitializer& ObjectInitializer);

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Players)
	TSubclassOf<APawn> BluePlayer;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Players)
	TSubclassOf<APawn> BeigePlayer;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Players)
	TSubclassOf<APawn> GreenPlayer;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Players)
	TSubclassOf<APawn> PinkPlayer;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Players)
	TSubclassOf<APawn> YellowPlayer;

	virtual void BeginPlay() override;
	virtual UClass* GetDefaultPawnClassForController(AController* InController) override;

	int32 InitialID;

};

Not entirely sure why the pawns arent being possesed correctly by their controllers. Their pawns just float a bit in midair, and the cameras for the two broken clients is skewed off. Replication is showing for these players though, as I can see the other characters moving. Any help is appreciated.

This is a known bug in 4.7 (and previous versions), it has been fixed for 4.8 thanks to Zak Middleton :slight_smile:

Basically, it happens when the new Pawn to possess doesn’t reach clients before the Possess call or something, I had a similar experience with this for ages, which I reported here.

Hopefully 4.8 isn’t far away now, so we can swap possession willy-nilly. Even with the fix though you don’t want to swap possession too many times in short succession, as it can still potentially fail. If you need an immediate fix, you could grab 4.8 source code in the master branch on GitHub and use that.