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;
}