A generic solution for the floating tank problem

I’m taking advantage of the newly created ToonTanksGameMode class and doing a line trace down to find the ground when it spawns the pawn.

ToonTanksGameMode.h

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/GameModeBase.h"
#include "ToonTanksGameMode.generated.h"

UCLASS()
class TOONTANKS_API AToonTanksGameMode : public AGameModeBase
{
	GENERATED_BODY()

public:
	virtual APawn* SpawnDefaultPawnAtTransform_Implementation(AController* NewPlayer, const FTransform& SpawnTransform) override;
};

ToonTanksGameMode.cpp

#include "ToonTanksGameMode.h"

#include "Components/CapsuleComponent.h"

APawn* AToonTanksGameMode::SpawnDefaultPawnAtTransform_Implementation(AController* NewPlayer, const FTransform& SpawnTransform)
{
	APawn* SpawnedPawn = Super::SpawnDefaultPawnAtTransform_Implementation(NewPlayer, SpawnTransform);
	
	if (SpawnedPawn)
	{
		if (const UCapsuleComponent* CapsuleComponent = Cast<UCapsuleComponent>(SpawnedPawn->GetRootComponent()))
		{
			// Perform a line trace to find the ground and position the pawn
			FHitResult Hit;
			const FVector Start = SpawnedPawn->GetActorLocation();
			const FVector End = Start - FVector(0.f, 0.f, 1000.f);  // Check below the Player Start
			FCollisionQueryParams Params;
			Params.AddIgnoredActor(SpawnedPawn);
			GetWorld()->LineTraceSingleByChannel(Hit, Start, End, ECC_Visibility, Params);

			if (Hit.bBlockingHit)
			{
				// Place the pawn on the hit location offsetting by the capsule half height with 0.1 margin to be safe 
				SpawnedPawn->SetActorLocation(Hit.Location + FVector(0, 0, CapsuleComponent->GetScaledCapsuleHalfHeight() + 0.1f));
			}		
		}
	}
	
	return SpawnedPawn;
}

It’s weird that we have this problem in the first place, though. I mean it’s natural to assume that people would want to use PlayerStart actor with smaller/bigger pawns than the standard one. So there must be an easier solution, I hope.

Privacy & Terms