언리얼 엔진 HitScan과 Projectile 비교

유영준·2023년 2월 21일
0

UE5 정보

목록 보기
3/5
post-thumbnail

사격이 들어간 게임을 만들때면 언리얼 엔진에서는 2가지 방식으로 피격 판정을 판별한다
Projectile 과 HitScan 방식이다 둘의 차이를 확인하고, 구현 방식을 알아보자

Projectile 과 HitScan

Projectile이란?

Projectile(투사체)는 언리얼 엔진에서 제공하는 ProjectileMovementComponent 를 통해 만들 수 있다

ProjectileMovementComponent 를 액터에 부착하게 되면 이 액터는 투사체가 되고, 날아가며 바람, 중력 등의 영향을

받는 현실적인 총알을 재현할 수 있게 된다

Projectile을 사용하는 방식은 일반적으로 많은 연산을 필요로 하지만 그만큼 더욱 현실적인 구현이 가능해진다

Projectile 방식은 저격총, 유탄 발사기 등에서 주로 쓰인다

(Projectile 방식의 솔져 우클릭)


HitScan 이란?

HitScan 방식은 언리얼 엔진의 Line Trace 를 통해 만들 수 있다

Line Trace 는 레이 캐스트를 사용하는 방식으로 쏘는 즉시 맞게 되며 Projectile 방식보다 연산이 적게 든다

대부분 근접한 위치에서 쏘게 되는 공격 등에 주로 쓰이게 된다

(HitScan 방식의 리퍼의 공격)


구현

언리얼에서 일인칭 템플릿을 만들게 되면 쉽게 Projectile 방식의 투사체 구현을 볼 수 있다

// Copyright Epic Games, Inc. All Rights Reserved.

#include "BulletTypeExampleProjectile.h"
#include "GameFramework/ProjectileMovementComponent.h"
#include "Components/SphereComponent.h"

ABulletTypeExampleProjectile::ABulletTypeExampleProjectile() 
{
	// Use a sphere as a simple collision representation
	CollisionComp = CreateDefaultSubobject<USphereComponent>(TEXT("SphereComp"));
	CollisionComp->InitSphereRadius(5.0f);
	CollisionComp->BodyInstance.SetCollisionProfileName("Projectile");
	CollisionComp->OnComponentHit.AddDynamic(this, &ABulletTypeExampleProjectile::OnHit);		
    // set up a notification for when this component hits something blocking

	// Players can't walk on it
	CollisionComp->SetWalkableSlopeOverride(FWalkableSlopeOverride(WalkableSlope_Unwalkable, 0.f));
	CollisionComp->CanCharacterStepUpOn = ECB_No;

	// Set as root component
	RootComponent = CollisionComp;

	// Use a ProjectileMovementComponent to govern this projectile's movement
	ProjectileMovement = CreateDefaultSubobject<UProjectileMovementComponent>(TEXT("ProjectileComp"));
	ProjectileMovement->UpdatedComponent = CollisionComp;
	ProjectileMovement->InitialSpeed = 3000.f;
	ProjectileMovement->MaxSpeed = 3000.f;
	ProjectileMovement->bRotationFollowsVelocity = true;
	ProjectileMovement->bShouldBounce = true;

	// Die after 3 seconds by default
	InitialLifeSpan = 3.0f;
}

UProjectileMovementComponent 를 생성하고, 시작 속도, 최고 속도 등을 지정하는 것을 볼 수 있다

반대로 HitScan 방식을 보자

			APlayerController* PlayerController = Cast<APlayerController>(Character->GetController());
			const FRotator StartRotation = PlayerController->PlayerCameraManager->GetCameraRotation();
			// MuzzleOffset is in camera space, so transform it to world space before offsetting from the character location to find the final muzzle position
			const FVector StartLocation = GetOwner()->GetActorLocation() + StartRotation.RotateVector(MuzzleOffset);

			const FVector EndLocation = StartLocation + (PlayerController->PlayerCameraManager->GetActorForwardVector() * 20000.0f);

			FCollisionObjectQueryParams ObjectParams;
			ObjectParams.AddObjectTypesToQuery(ECC_WorldStatic);

			FHitResult HitResult;
			FCollisionQueryParams TraceParams(FName(TEXT("LineTrace")), true);

			bool bHit = GetWorld()->LineTraceSingleByObjectType(HitResult, StartLocation, EndLocation, ObjectParams, TraceParams);

			if (bHit) DrawDebugLine(GetWorld(), StartLocation, HitResult.Location, FColor::Green, false, 2.0f, 0, 0.5f);
			else	  DrawDebugLine(GetWorld(), StartLocation, EndLocation,		   FColor::Red,   false, 2.0f, 0, 0.5f);

HitScan 방식은 LineTraceSingleByObjectType을 통해 구현해주었다

콜리전 체크 방식을 사용했고, 닿는 게 있다면 초록색으로 라인을, 없다면 빨간색 라인을 그리도록 설정했다

간단하게 두 방식을 바꿀 수 있게 설정 후 잘 적용되는지 확인해 보았다

profile
토비폭스가 되고픈 게임 개발자

0개의 댓글