스칼라곱, 시점 변경 시 카메라 로테이션 보간

김지윤·2024년 10월 1일
0

UE5

목록 보기
2/16
post-thumbnail

기존엔 우클릭 시 어깨 너머로 확대시키던 로직이었는데, 1인칭으로 시점 변환하도록 만들어보고 싶어서 구현해봤다. 현재는 카메라 보간이 적용되지 않은 상태다.

fpsCamera = CreateDefaultSubobject<UCameraComponent>(TEXT("fpsCamera"));
fpsCamera->SetupAttachment(GetMesh(), FName("head"));
fpsCamera->bUsePawnControlRotation = true; // 1인칭이 되면 카메라 따라 캐릭터가 회전해야 함
fpsCamera->SetRelativeRotation(FRotator{ 0.f, 90.f, -90.f });
fpsCamera->SetRelativeLocation(FVector{ 3.f, 12.f, 0.f });

우선 위처럼 fpsCamera를 선언하고, 캐릭터 Mesh의 Bone 중 head라는 이름을 가진 소켓에 붙인 뒤 위치를 조금 조정해줬다.

그럼 이렇게 잘 붙는다.

void AMainCharacter::Aim()
{
	if (bAiming)
		StopAiming();
	else
		Aiming();
}
void AMainCharacter::Aiming()
{
	if (!HUD->bIsInventoryVisible)
	{
		bAiming = true;
		bUseControllerRotationYaw = true;
		GetCharacterMovement()->MaxWalkSpeed = PlayerStatComponent->GetAimingWalkSpeed();

		fpsCamera->Activate();
		tpsCamera->Deactivate();

		InterpolateCameraRotation(tpsCamera, fpsCamera);
	}
}

void AMainCharacter::StopAiming()
{
	bAiming = false;
	if (!bWeaponEquip)
		bUseControllerRotationYaw = false;
	GetCharacterMovement()->MaxWalkSpeed = PlayerStatComponent->GetWalkSpeed();

	tpsCamera->Activate();
	fpsCamera->Deactivate();

	InterpolateCameraRotation(fpsCamera, tpsCamera);
}

그 다음 우클릭 시 Aim()을 실행하도록 할당, 현 상태에 따라 Aiming()과 StopAiming()을 번갈아 실행한다.
가장 아래 InterpoalteCameraRotation이 이번 글 주인공인 카메라 보간이다.

void AMainCharacter::InterpolateCameraRotation(UCameraComponent* FromCamera, UCameraComponent* ToCamera)
{
	FVector TraceStart{ FVector::ZeroVector };
	FVector TraceEnd{ FVector::ZeroVector };
	float Distance = 1000.f;

	TraceStart = FromCamera->GetComponentLocation();
	TraceEnd = { TraceStart + (FromCamera->GetComponentRotation().Vector() * Distance) };

	FCollisionQueryParams QueryParams;
	QueryParams.AddIgnoredActor(this);
	FHitResult TraceHit;

	if (GetWorld()->LineTraceSingleByChannel(TraceHit, TraceStart, TraceEnd, ECC_Visibility, QueryParams))
	{
		// 스칼라곱을 이용한 카메라 보간 정도 구하기
		FVector Direction = (TraceHit.ImpactPoint - ToCamera->GetComponentLocation());
		FRotator NewRotation = Direction.Rotation();

		Controller->SetControlRotation(NewRotation);
	}
	else
	{
		// 카메라 보간 필요 없는 경우
		return;
	}
}

LineTrace로 현재 바라보고 있는 위치의 Vector값을 구하고, 스칼라곱을 이용해 Rotation을 구해준다.

V = B - A 이므로, TraceHit.ImpactPoint - ToCamera->GetComponentLocation() 라는 식이 나온다.
최종적으로 V에서 Rotation을 얻어내 Controller의 Rotation을 조정해준다.

3인칭으로 돌아올 때 유격이 있다. 캐릭터를 움직여 측면이나 후면을 바라보게 한 뒤 1인칭으로 전환할 때도 유격이 존재한다.
이유는 정확히 모르겠지만 Camera로 얻은 Rotation과 Controller가 필요로 하는 Rotation이 살짝 달라서 그런 게 아닌가 추측해본다.
그래도 이 정도의 유격이라면 실제 게임이라 가정했을 때 플레이에 큰 지장은 없을 것 같다.

사실 TimelineCurve를 이용해 자연스럽게 전환되는 걸 만들어보려고 했는데, 방법을 찾지 못 해 이런 식의 전환으로 구현했다. 공부가 더 필요할 듯 싶다.

profile
공부한 거 시간 날 때 작성하는 곳

0개의 댓글