Why are the players only spawning some times?

Hi, I’ve set up my GameMode’s subclass to spawn 4 local players at BeginPlay. There are many PlayerStart actors over the level. The problem is the randomness here: some time all of them are spawned, some times only 3 of them, or 2 or 1. The only one that always spawns is the one with player index 0, not spawned through C++. The others may or may not (it might appear the one with player index 3, but not the one with 1).

Here’s the code. What might be causing this?

void AGameModePush::BeginPlay()
{
	Super::BeginPlay();

	if (GEngine)
	{

		FString Error1;
		FString Error2;
		FString Error3;

		auto It1 = GetWorld()->GetPlayerControllerIterator();
		APlayerController* Player1 = *It1;
		AGameModePush::ChoosePlayerStart(Player1);

		auto It2 = GetWorld()->GetPlayerControllerIterator();
		APlayerController* Player2 = *It2;
		AGameModePush::ChoosePlayerStart(Player2);

		auto It3 = GetWorld()->GetPlayerControllerIterator();
		APlayerController* Player3 = *It3;
		AGameModePush::ChoosePlayerStart(Player3);

		GEngine->GameViewport->CreatePlayer(1, Error1, true);
		GEngine->GameViewport->CreatePlayer(2, Error2, true);
		GEngine->GameViewport->CreatePlayer(3, Error3, true);
		GEngine->AddOnScreenDebugMessage(-1, 15.f, FColor::Yellow, Error1);
		GEngine->AddOnScreenDebugMessage(-1, 15.f, FColor::Yellow, Error2);
		GEngine->AddOnScreenDebugMessage(-1, 15.f, FColor::Yellow, Error3);


	}


}


AActor* AGameModePush::ChoosePlayerStart(AController* Player)
{
	TArray<APlayerStart*> PreferredSpawns;
	TArray<APlayerStart*> FallbackSpawns;

	for (int32 i = 0; i < PlayerStarts.Num(); i++)
	{
		APlayerStart* TestSpawn = PlayerStarts[i];
		//if (IsSpawnpointAllowed(TestSpawn, Player))
		//{
			if (IsSpawnpointPreferred(TestSpawn, Player))
			{
				PreferredSpawns.Add(TestSpawn);
			}
			else
			{
				FallbackSpawns.Add(TestSpawn);
			}
		//}
	}

	APlayerStart* BestStart = NULL;
	if (PreferredSpawns.Num() > 0)
	{
		BestStart = PreferredSpawns[FMath::RandHelper(PreferredSpawns.Num())];
	}
	else if (FallbackSpawns.Num() > 0)
	{
		BestStart = FallbackSpawns[FMath::RandHelper(FallbackSpawns.Num())];
	}

	return BestStart ? BestStart : Super::ChoosePlayerStart(Player);
}

bool AGameModePush::IsSpawnpointPreferred(APlayerStart* SpawnPoint, AController* Player) const
{
	ACharacter* MyPawn = Player ? Cast<ACharacter>(Player->GetPawn()) : NULL;
	if (MyPawn)
	{
		const FVector SpawnLocation = SpawnPoint->GetActorLocation();
		for (FConstPawnIterator It = GetWorld()->GetPawnIterator(); It; ++It)
		{
			ACharacter* OtherPawn = Cast<ACharacter>(*It);
			if (OtherPawn && OtherPawn != MyPawn)
			{
				const float CombinedHeight = (MyPawn->CapsuleComponent->GetScaledCapsuleHalfHeight() + OtherPawn->CapsuleComponent->GetScaledCapsuleHalfHeight()) * 2.0f;
				const float CombinedRadius = MyPawn->CapsuleComponent->GetScaledCapsuleRadius() + OtherPawn->CapsuleComponent->GetScaledCapsuleRadius();
				const FVector OtherLocation = OtherPawn->GetActorLocation();

				// check if player start overlaps this pawn
				if (FMath::Abs(SpawnLocation.Z - OtherLocation.Z) < CombinedHeight && (SpawnLocation - OtherLocation).Size2D() < CombinedRadius)
				{
					return false;
				}
			}
		}
	}

	return true;
}

Hi, there are more than 4 player starts and only 4 players to create, so blocking shouldn’t be a problem.

Did you make sure your PlayerStart that randomed is not blocked?

#ShooterGame

Check out shooter game game mode

you need that code for choosing spawn locations and avoiding ones that are blocked

:slight_smile:

I’ve posted the code elsewhere on this forum already

#Code Link

Rama

Hi, Rama, thanks for that, but I forgot to post another part of the code involved there, that were pair of functions based just on ShooterGame’s gamemode.

You might check out the edited part in the first post. The problem with the only-sometimes-spawned players is with the full snippet of code seen in the first post.

Any ideas?

I have the same problem currently. I am checking for collisions, but in the log I get a message on the occasions when the spawn fails “Couldn’t spawn Pawn of type MyCharacter_C at PlayerStart1” where PlayerStart1 changes since it has been randomized.

However, in the IsSpawnpointPreferred function, the Player->GetPawn() call fails to cast to ACharacter. I do not know why it is failing, but that is what is causing the spawning of the player to fail.

Any ideas as to why the initial cast is failing?

That’s pretty weird, because since all the players are of the same class the cast should fail or succeed in all cases.

Do you still have the problem or have you found a solution? If you have the issue did you check if your Player->GetPawn also fails?

Anyway I have found something that works. I have looked at the ShooterGame code and was assuming that the IsSpawnpointPreferred function was working properly there. Then I started wondering what would happen if it was also failing the cast as described earlier. I found that a FailedToSpawnPawn function existed for APlayerController. After overriding as follows, I now get successful spawns everytime (I mean, at least it retries until successfull.)

void AMyPlayerController::FailedToSpawnPawn()
{
	GetWorld()->GetAuthGameMode()->RestartPlayer(this);
}

Hi again @Urquan, thanks for your information, I’ve now checked out and overriden that function in my player controller subclass after reading what you did, but I’m not getting successful results yet: now the editor crashes and I get a Log file of more than 5MB saying what shown below, only complaining about a different player start each time.

[2014.04.21-15.06.26:250][409]LogGameMode:Warning: Couldn’t spawn Pawn of type my_character_class
[2014.04.21-15.06.26:250][409]LogGameMode:Warning: failed to spawn player at PlayerStart_2

I’m going to check my code better (the piece posted in the first post), but if someone has any suggestions I will read them thankfuly.

This randomness has automatically been solved when updating to UE 4.1.