Unreal5 맞은 방향 알아내기 CrossProduct(외적) c++

Unreal5 맞은 방향 알아내기 CrossProduct c++

Dot Product는 두 벡터의 사잇각이 0-180도 사이에 있을 때 값을 계산합니다. 즉, 두 벡터가 평행하면 값이 최대가 되고, 직교하면 0이 되며, 반대 방향이면 값이 최소가 됩니다. 따라서 두 벡터가 오른쪽인지 왼쪽인지 알 수 없었습니다.그래서 이번에는 Cross Product를 사용해 보겠습니다.

[프로그래밍/언리얼] - Unreal5 Dot Product(내적) C++

 

Unreal5 Dot Product(내적) C++

Unreal5 Dot Product(내적) C++ 저번글에서 간단한 Hit를 구현했는데 좀 더 살을 붙여보려고 합니다. 이번 글에서는 Dot Product를 이용해 Player가 때리는 각도를 알아보려고 합니다. [프로그래밍/언리얼] - U

intunknown.tistory.com

  • CrossProduct(외적).
  • CrossProduct 코드 추가.
  • 중간 점검.
  • 애니메이션 코드 추가 및 추가 설정.
  • 결과.

CrossProduct(외적).

https://en.wikipedia.org/wiki/Cross_product

 

Cross product - Wikipedia

From Wikipedia, the free encyclopedia Mathematical operation on vectors in 3D space In mathematics, the cross product or vector product (occasionally directed area product, to emphasize its geometric significance) is a binary operation on two vectors in a

en.wikipedia.org

CrossProduct는 두 벡터를 곱해서 수직인 벡터를 반환하는 연산입니다. A*B=C로 표현할 수 있으며, 결과 벡터 C의 방향은 A와 B가 이루는 평면에 수직합니다.

 

언리얼에서는 왼손법칙을 따르기 때문에 CrossProduct를 계산했을 때, Z값이 양수라면 오른쪽, 음수라면 왼쪽이 됩니다.

CrossProduct 코드 추가.

Enemy.cpp의 GetHit만 수정했습니다.

log창에 left인지 right인지만 출력하는 코드입니다.

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);
	
	//Cross Product
	const FVector CrossProduct = FVector::CrossProduct(Forward, ToHit);
	if (CrossProduct.Z < 0) {
		//CrossProduct가 음수일때.
		UE_LOG(LogTemp, Log, TEXT("Left"));
	}
	else {
		UE_LOG(LogTemp, Log, TEXT("Right"));
	}
}

중간 점검.

왼쪽에서 찌르니까 Left, 오른쪽에서 찌르니까 Right 잘 나오네요!

애니메이션 관련 코드 추가 및 추가 설정.

이제 Enemy.h에서 UanimMontage를 하나 선언해 줍니다.

// 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"
class UAnimMontage;
UCLASS()
class SLAYER_API AEnemy : public ACharacter, public IHitInterface
{
	GENERATED_BODY()
public:
	AEnemy();
	virtual void Tick(float DeltaTime) override;
protected:
	virtual void BeginPlay() override;
	virtual void GetHit(const FVector& ImpactPoint) override;
    UPROPERTY(EditDefaultsOnly, Category = Combat)
	UAnimMontage* HitReactMontage;
};

Enemy.cpp에서 Animation Montage를 재생하는 코드를 추가해 줍니다.

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);
	//Cross Product
	const FVector CrossProduct = FVector::CrossProduct(Forward, ToHit);
	if (CrossProduct.Z < 0) {
		//CrossProduct가 음수일때.
		Theta *= -1;
	}
	FName Section("FromBack");
	if (Theta >= -45.f && Theta < 45.f) {
		Section = FName("FromFront");
	}
	else if (Theta >= -135.f && Theta < -45.f) {
		Section = FName("FromLeft");
	}
	else if (Theta >= 45.f && Theta < 135.f) {
		Section = FName("FromRight");
	}
	UAnimInstance* AnimInstance = GetMesh()->GetAnimInstance();
	if (AnimInstance && HitReactMontage) {
		AnimInstance->Montage_Play(HitReactMontage);
		AnimInstance->Montage_JumpToSection(Section, HitReactMontage);
	}
}

Animation montage도 만들고 코드에 맞게 Section도 추가해 줍니다.

그리고 Section이 이어서 재생되지 않도록 Clear도 눌러줍니다.

BP_Monster(Enemy)에서 Montage도 추가해 줍니다.

결과.

재생하려는 애니메이션에 RootMotion이 있어서 이것도 설정해 주고 때리면 작동은 됩니다.

근데 문제는 현재 무기 boxCollsion이벤트가 상시 활성화상태라서 스치기만 해도 애니메이션이 발동하네요. ㅋㅋㅋ

이것 때문에 한번 공격에 애니메이션이 섞인다고 해야 되나? 

일단은 다른거 만드는 중이라.. 나중에 수정해야겠네요.

 

Designed by JB FACTORY