1. 범위 순회 - 종료 조건 전달하기 (AKillEmAllGameMode)
미래에 적을 다수 배치하고 승리하는 조건을 고려하기 위해, 모든 폰의 컨트롤러에게 게임이 끝났다는 조건을 전달해야 한다.
UCLASS()
class SIMPLESHOOTER_API AKillEmAllGameMode : public ASimpleShooterGameModeBase
{
GENERATED_BODY()
public:
virtual void PawnKilled(APawn* PawnKilled) override;
private:
void EndGame(bool bIsPlayerWinner);
};
아래 헤더를 추가한다.
#include "EngineUtils.h"
#include "GameFramework/Controller.h"
void AKillEmAllGameMode::PawnKilled(APawn* PawnKilled)
{
Super::PawnKilled(PawnKilled);
auto PlayerController = Cast<APlayerController>(PawnKilled->GetController());
if (PlayerController != nullptr)
{
EndGame(false);
}
}
void AKillEmAllGameMode::EndGame(bool bIsPlayerWinner)
{
// Scene의 모든 컨트롤러를 호출하여 GameHasEnded 호출
for (AController* Controller : TActorRange<AController>(GetWorld()))
{
bool bIsWinner = Controller->IsPlayerController() == bIsPlayerWinner;
// 승리 시 포커스를 플레이어 폰에 유지
Controller->GameHasEnded(Controller->GetPawn(), bIsWinner);
}
}
TActorRange 템플릿을 사용하여 월드 내의 컨트롤러를 모두 찾고 범위 순회를 실행한다.
이후 조건을 체크하여, 플레이어 컨트롤러이며 플레이어가 이겼다면 GameHasEnded에 True를 넘겨 승리했다는 것을 알린다.
그 이외의 AI 컨트롤러이며 플레이어가 패배했다면 False를 넘겨 게임이 패배로 끝났다는 것을 알린다.
위와 같이 코드를 작성하면 3가지 예외 케이스를 한 줄로 줄일 수 있다.
2. 승리 조건
(1) 사망 판정 - ShooterAIController
폰의 사망을 판정할 수 있도록 코드를 추가한다.
bool AShooterAIController::IsDead() const
{
AShooterCharacter* ControlledCharacter = Cast<AShooterCharacter>(GetPawn());
if (ControlledCharacter)
{
return ControlledCharacter->IsDead();
}
return true;
}
(2) 승리 조건 추가 - ShooterPlayerController
private:
UPROPERTY(EditAnywhere)
TSubclassOf<class UUserWidget> LoseScreenClass;
UPROPERTY(EditAnywhere)
TSubclassOf<class UUserWidget> WinScreenClass;
void AShooterPlayerController::GameHasEnded(AActor* EndGameFocus, bool bIsWinner)
{
Super::GameHasEnded(EndGameFocus, bIsWinner);
if (bIsWinner)
{
// UI 노출
UUserWidget* WinScreen = CreateWidget(this, WinScreenClass);
if (WinScreen)
{
WinScreen->AddToViewport();
}
}
else
{
// UI 노출
UUserWidget* LoseScreen = CreateWidget(this, LoseScreenClass);
if (LoseScreen)
{
LoseScreen->AddToViewport();
}
}
// 재시작
GetWorldTimerManager().SetTimer(RestartTimer, this, &APlayerController::RestartLevel, RestartDelay);
}
이제 플레이어가 이겼을 경우도 판정해야하므로 코드를 수정한다.
(3) 승리 조건 판정하기 - KillEmAllGameMode
아래 헤더를 추가한다.
#include "ShooterAIController.h"
void AKillEmAllGameMode::PawnKilled(APawn* PawnKilled)
{
Super::PawnKilled(PawnKilled);
auto PlayerController = Cast<APlayerController>(PawnKilled->GetController());
if (PlayerController != nullptr)
{
EndGame(false);
}
// 월드에 있는 AI 슈터를 찾기
// IsDead == false
// return;
// AI 슈터가 더 이상 없으면 게임 종료
for (AShooterAIController* Controller : TActorRange<AShooterAIController>(GetWorld()))
{
// 아직 사망하지 않았다면 종료하지 않음
if (!Controller->IsDead())
return;
}
// 모두 사망했다면 종료
EndGame(true);
}
이제 TActorRange를 통해 AI 컨트롤러를 전부 찾아 사망을 판정한다.
하나라도 살아있다면 아직 게임이 종료되지 않은 것이므로 함수를 얼리 리턴한다.
'UE 5 스터디 > C++' 카테고리의 다른 글
12. 패배 조건 - 게임 재시작, UI 위젯 스폰 (1) | 2024.03.08 |
---|---|
11. 트러블 슈팅 (1) | 2024.03.08 |
10. 비헤이비어 트리 - 서비스 노드 (0) | 2024.03.08 |
9. 비헤이비어 트리 노드 생성하기 (0) | 2024.03.08 |
8. 비헤이비어 트리와 블랙 보드 (0) | 2024.03.07 |