Unreal5 Dot Product(내적) C++

Unreal5 Dot Product(내적) C++

저번글에서 간단한 Hit를 구현했는데 좀 더 살을 붙여보려고 합니다.

이번 글에서는 Dot Product를 이용해 Player가 때리는 각도를 알아보려고 합니다.

[프로그래밍/언리얼] - Unreal5 Hit C++

 

Unreal5 Hit C++

Unreal5 Hit C++ 안녕하세요. 저번 글에서 공격 애니메이션을 추가했습니다. 이번 글에서는 Box Component를 이용해 공격한 위치를 보여주도록 하겠습니다. [프로그래밍/언리얼] - Unreal5 Attack Animation C++ U

intunknown.tistory.com

  • Dot Product(내적).
  • 코드 작성.
  • 결과.

DotProduct(내적).

Enemy를 어제 구현한 Hit로 때렸을 때 각도를 알아보겠습니다.

일단 이 글에서는 Dot Product에 대한 코드만 작성할 예정입니다.

구한 각도는 아래 사진처럼 (0-180도)로 표시됩니다.

아래처럼 내적을 사용하면 Player가 어느 각도에서 공격했는지 구할 수 있습니다.

이 부분을 아래에서 코드로 구현할 예정입니다.

코드 작성.

먼저 HitInterface c++ class를 하나 만들어줬습니다.

내용은 별 것 없습니다.

#pragma once

#include "CoreMinimal.h"
#include "UObject/Interface.h"
#include "HitInterface.generated.h"

// This class does not need to be modified.
UINTERFACE(MinimalAPI)
class UHitInterface : public UInterface
{
	GENERATED_BODY()
};

/**
 * 
 */
class SLAYER_API IHitInterface
{
	GENERATED_BODY()

	// Add interface functions to this class. This is the class that will be inherited to implement this interface.
public:
	virtual void GetHit(const FVector& ImpactPoint)=0;
};

Enemy.h에서 HitInterface를 include해주고,  IHitInterface를 상속합니다.

HitInterface에 GetHit를 선언했으니 Enemy.h에서는 사용하기 위해 override 해줍니다.

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Character.h"
#include "Interface/HitInterface.h"
#include "Enemy.generated.h"

UCLASS()
class SLAYER_API AEnemy : public ACharacter,public IHitInterface 
{
	GENERATED_BODY()

public:
	// Sets default values for this character's properties
	AEnemy();
	virtual void GetHit(const FVector& ImpactPoint) override;
protected:
	// Called when the game starts or when spawned
	virtual void BeginPlay() override;
	//void DirectHitReact(const FVector& impactPoint);
public:	
	// Called every frame
	virtual void Tick(float DeltaTime) override;

	// Called to bind functionality to input
	virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
};

이제 GetHit를 구현하겠습니다.

FVector ImpactPoint 매개변수로 충격지점을 받아와서 해당 지점에 대한 디버깅 구를 그리고, 적 캐릭터가 바라보는 방향벡터와 충격 지점과의 각도를 위에서 설명한 방법을 통해 계산해서 로그에 출력하는 함수입니다.

이를 통해 적 캐릭터가 어떤 방향을 바라보고 있을 때 어느 방향으로 공격받았는지 알 수 있습니다.

하지만 아직 왼쪽에서 공격을 받았는지 오른쪽에서 공격을 받았는지는 구분할 수 없으며, 이를 위해 다음 글에서 Cross Product(외적)을 이용해 알아낼 예정입니다.

void AEnemy::GetHit(const FVector& ImpactPoint)
{
	DrawDebugSphere(GetWorld(), ImpactPoint, 10.f,15, FColor::Orange, false, 3.f);
	const FVector Forward = GetActorForwardVector();
	const FVector Impact (ImpactPoint.X, ImpactPoint.Y, GetActorLocation().Z);
	const FVector ToHit = (ImpactPoint - GetActorLocation()).GetSafeNormal();
	//Dot Product
	const double CosTheta = FVector::DotProduct(Forward, ToHit);
	double Theta = FMath::Acos(CosTheta);
	Theta = FMath::RadiansToDegrees(Theta);
	UE_LOG(LogTemp, Log, TEXT("%f"),Theta);
}

마지막으로 Weapon.cpp의 OnBoxOverlap함수입니다.

Enemy의 GetHit 함수에 impact point를 전달합니다.

void AWeapon::OnBoxOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{
	const FVector Start = BoxTraceStart->GetComponentLocation();
	const FVector End = BoxTraceEnd->GetComponentLocation();
	TArray<AActor*> ActorsToIgnore;
	ActorsToIgnore.Add(this);
	//#include "Kismet/KismetSystemLibrary.h"
	FHitResult BoxHit;
	UKismetSystemLibrary::BoxTraceSingle(this,Start,End, FVector(5.f, 5.f, 5.f),BoxTraceStart->GetComponentRotation(), ETraceTypeQuery::TraceTypeQuery1,
		false,ActorsToIgnore,EDrawDebugTrace::None, BoxHit,true);
	//if (GetWorld()) {
	//	DrawDebugSphere(GetWorld(),BoxHit.ImpactPoint,20.f,15,FColor::Red,false,5.f);
	//}
	if (BoxHit.GetActor()) {
		/*Actor를 때렸을 때*/
		IHitInterface* HitInterface = Cast<IHitInterface>(BoxHit.GetActor());
		if (HitInterface) {
			HitInterface->GetHit(BoxHit.ImpactPoint);
		}
	}
}

결과.

이런식으로 각도가 표시됩니다.

 

Designed by JB FACTORY