Registering AI controlled players as players in multiplayer

I’m trying to add some AI players to my multiplayer project for testing purposes. I’ve created the AIController class and set is as the AI controller on my character pawn. I handle spawning in the GameMode class like so:

void AGameplayGameMode::SpawnBot() {
  FActorSpawnParameters SpawnParams;
  SpawnParams.bNoFail = true;
  FTransform SpawnPos;
  AShootGunCharacter* Bot = GetWorld()->SpawnActor<AShootGunCharacter>(BotCharacter, SpawnPos, SpawnParams);
  ABotController* Controller = GetWorld()->SpawnActor<ABotController>(BotController, SpawnPos, SpawnParams);

  if (Bot != nullptr && Controller != nullptr) {
    GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Yellow, TEXT("Spawned bot"));

    APlayerStateMatch* PlayerState = Controller->GetPlayerState<APlayerStateMatch>();
    PlayerState->SetPlayerTeam(1);

    const FTransform SpawnTransform = this->FindPlayerStart(Controller)->GetActorTransform();
    Bot->TeleportTo(SpawnTransform.GetLocation(), SpawnTransform.GetRotation().Rotator());
    Controller->Possess(Bot);
  }
}

Then I call this function in my GameState class like so:

void AGameStateMatch::OnRep_MatchState() {
  Super::OnRep_MatchState();

  if (GetMatchState() == MatchState::WaitingToStart) {
    AGameplayGameMode* GameMode = Cast<AGameplayGameMode>(AuthorityGameMode);
    if (GameMode != nullptr) {
      if (GameMode->SpawnBots) {
        for (int i = 0; i < GameMode->NumBotsToSpawn; i++) {
          GameMode->SpawnBot();
        }
      }
    }
  }
  /*
  ... rest of function
  */
}

This all works fine in terms of spawning the bots and they’ll move around and everything. My issue is that the game doesn’t recognize the bots as players. They have PlayerState, but if I try to shoot them, the game immediately crashes.

I feel like this is in part due to the code in the normal PlayerController that dispatches commands to the server for taking damage, increasing score/kills/etc. Does this mean I need to reimplement all of that logic in the AI Controller as well? Because that’ll get really annoying and messy

No these functionalities should be moved to more appropriate (and shared) classes.

PlayerController is supposed to manage player camera and route player input to its character.

Damage should be handled from weapon to character. PlayerController shouldn’t be involved in the process, until the very last step when you want to show on-screen feedback (dmg numbers, hurt screen, etc.).

Similarly, death and scoring should be handled from character to GameMode, and then replicated via GameState/PlayerState for scoreboard widgets. Again, no PlayerController involved.

Read up on the Gameplay Framework.

1 Like