My GameMode check condition

My GameMode end condition check implementation. Thought I would share. I created a private member function:

#include <optional>
/// ...

	/**
	* Returns an optional with true if player wins, false if player loses.  An empty optional indicates the game is not over.
	*/
	std::optional<bool> CheckEndGameCondition(APawn* PawnKilled) const;

Note I updated my Build.cs file to enable C++17 which is currently the latest version allowed by the engine (C++20 not yet supported as of 4.26.2 - most likely because one of the supported platforms doesn’t support it as VS 2019 does)

I also like to make use of the standard C++ algorithms where I can so opted to use std::any_of.

#include <algorithm>
// ...
std::optional<bool> ASinglePlayerEnemyHuntGameMode::CheckEndGameCondition(APawn* PawnKilled) const
{
	AController* PawnController = Cast<AController>(PawnKilled->GetController());
	if (PawnController && PawnController->IsPlayerController())
	{
		return false;
	}
	
	auto Begin = TActorIterator<AShooterAIController>(GetWorld());
	auto End = TActorIterator<AShooterAIController>(EActorIteratorType::End);

	// TODO: What if multiple players killed at the same time?
	if (Begin == End)
	{
		UE_LOG(LogTemp, Warning, TEXT("No actors left in the level! Marking game as lost"));
		return false;
	}

	bool AnyAIRemains = std::any_of(Begin, End, [](auto ShooterAIController) {
		return !ShooterAIController->IsDead();
	});

	return AnyAIRemains ? std::nullopt : std::make_optional(true) ;
}

I then call it in PawnKilled with

	auto GameOverOptional = CheckEndGameCondition(PawnKilled);
	if (!GameOverOptional)
	{
		return;
	}

	UE_LOG(LogTemp, Display, TEXT("Game ended"));

	EndGame(*GameOverOptional);

So I found a bug in the above code. I noticed that sometimes it would flash the win screen and then immediately switch to the lose screen. Initially I thought it was because both actors killed each other, but also noticed my character didn’t show a death animation. The issue was very apparent once the Health bar HUD was added to the game. The issue was with the empty actors case below my TODO comment in the code snippet. It seems that when the level restarts, it will “kill” all the actors and also clear them out from the scene graph and then GameEnded is being called again with no actors. The fix is simple, return a std::nullopt instead of false for that case as we can handle empty actors as the game not ended so that it doesn’t fire twice:

	// TODO: What if multiple players killed at the same time?
	if (Begin == End)
	{
		UE_LOG(LogTemp, Warning, TEXT("No actors left in the level! Returning std::nullopt"));
		return std::nullopt;
	}

Privacy & Terms