Possessing a pawn group in turn (Editor MP Dedicated with 1 Client)

*** CLOSED, can’t reproduce the problem in UE4.1 ***

Hello there,

i’m currently trying to spawn 4 pawns during the SpawnDefaultPawnFor call in my custom game mode. All 4 pawns are to be controlled by the same controller sequentially, not concurrently. During runtime, I can successfuly possess each pawn in turn using key input I defined.
However, the first time I possess any of the other pawns Nr. 2 to 4, the orientation and animation cycles are wrong: The pawns remain facing north in the client and seems to be in a walk animation, though they should be idling.
After possessing each of the 4 pawns, they suddenly behave correctly as expected when navigating with them.

If I connect a second client to the session, the navigation and animation of the pawns from the 1st client look correct though, even as they show up wrong in the initial, 1st client’s window.
Also, this behaviour occurs on all maps i’m testing with when a second client is connected too.

Running without the dedicated server handles fine, I can switch between the 4 pawns and they move and turn correctly immediately on first possession as expected. I’m assuming it’s a replication issue, I’m probably missing something I need to set on the ACharacter derived class.

My questions are:

  1. Am I missing some initialization of the pawn when it’s first spawned?
  2. Is it correct to spawn all pawns of the group in the call SpawnDefaultPawnFor of the game mode? At the end of the call, I store the APawn references in the controller class they belong to.

This is the relevant code:


APawn* AUE4_GriClientGameMode::SpawnDefaultPawnFor(AController* NewPlayer, AActor* StartSpot)
{
	AMyPlayerController* myController = Cast<AMyPlayerController>(NewPlayer);

	// don't allow pawn to be spawned with any pitch or roll 
	FRotator StartRotation(ForceInit);
	StartRotation.Yaw = StartSpot->GetActorRotation().Yaw;
	FVector StartLocation = StartSpot->GetActorLocation();

	FActorSpawnParameters SpawnInfo;
	SpawnInfo.Instigator = Instigator;

	myController->SetTeamIndex(NumPlayers);
	myController->ResetCurrentTeamMemberIndex();

	for (int32 spawnIndexY = 0; spawnIndexY <= 1; spawnIndexY++)
	{
		for (int32 spawnIndexX = 0; spawnIndexX <= 1; spawnIndexX++)
		{
			int32 spawnIndex = spawnIndexX + (2 * spawnIndexY);

			FVector newLocation;
			newLocation.X = StartLocation.X + (-100.0f * spawnIndexX);
			newLocation.Y = StartLocation.Y + (100.0f * spawnIndexY);
			newLocation.Z = StartLocation.Z + 0.0f;

			APawn *newPawn = GetWorld()->SpawnActor<APawn>(GetDefaultPawnClassForController(myController), newLocation, StartRotation, SpawnInfo);
			newPawn->SpawnDefaultController();
			
			myController->SetTeamMemberPawn(spawnIndex, newPawn);
		}
	}

	return myController->GetActiveTeamMemberPawn();
}

Thanks for any pointers here,
Hairein

Hi Hairein

I might have this wrong, but you said that “All 4 Pawns are to be controlled by the same Controller sequentially, not concurrently”, yet your “newPawn->SpawnDefaultController();” is within your for loops, thus you’ll actually spawn multiple controllers, each controlling one pawn, not just one controller possessing each pawn at a time. Could that not be your problem ?

If that’s the case, you should move the “newPawn->SpawnDefaultController();” to just before “return myController->GetActiveTeamMemberPawn();”. That way you’ll only spawn one controller and you can iterate through all your newly created pawns one at a time and posses them.

Thank you Ad3ViLl,

sadly this variation produced exactly the same result as before. I also tried not calling any SpawnDefaultController() methods in both code variations. My initial assumption was that any controllers spawned for the pawns would be cleared by the possession which probably takes place after the GameMode returns from the SpawnDefaultPawnFor().
What I don’t really understand yet is why the pawns each behave correctly the second time they are possessed at runtime, but my assumption is a missing initialization step which is done automatically later when I change possession.

I’m using UE4 v4.0.2 regular install not built from GitHub code.

This is the current code:


APawn* AUE4_GriClientGameMode::SpawnDefaultPawnFor(AController* NewPlayer, AActor* StartSpot)
{
	AMyPlayerController* myController = Cast<AMyPlayerController>(NewPlayer);

	// don't allow pawn to be spawned with any pitch or roll 
	FRotator StartRotation(ForceInit);
	StartRotation.Yaw = StartSpot->GetActorRotation().Yaw;
	FVector StartLocation = StartSpot->GetActorLocation();

	FActorSpawnParameters SpawnInfo;
	SpawnInfo.Instigator = Instigator;

	myController->SetTeamIndex(NumPlayers);
	myController->ResetCurrentTeamMemberIndex();

	for (int32 spawnIndexY = 0; spawnIndexY <= 1; spawnIndexY++)
	{
		for (int32 spawnIndexX = 0; spawnIndexX <= 1; spawnIndexX++)
		{
			int32 spawnIndex = spawnIndexX + (2 * spawnIndexY);

			FVector newLocation;
			newLocation.X = StartLocation.X + (-100.0f * spawnIndexX);
			newLocation.Y = StartLocation.Y + (100.0f * spawnIndexY);
			newLocation.Z = StartLocation.Z + 0.0f;

			APawn *newPawn = GetWorld()->SpawnActor<APawn>(GetDefaultPawnClassForController(myController), newLocation, StartRotation, SpawnInfo);
		
			myController->SetTeamMemberPawn(spawnIndex, newPawn);
		}
	}

	myController->GetActiveTeamMemberPawn()->SpawnDefaultController();

	return myController->GetActiveTeamMemberPawn();
}

Regards.

Is there anyway you can show us your code for possessing the pawns as I cannot seem to find anything else wrong with the code you already showed us ?

Hi again,

sure, it’s just learning code so i’ll provide the source.zip with the 5 classes here (~114KB).
Any help would be greatly appreciated!

Thanks for taking the time,
Hairein