[UE5] 언리얼5 C++ - AI 점프공격 (DropDown)

AnJH·2024년 6월 4일

BehaviorTree_DropDown

DropDown 모션은 애니메이션 몽타주를 통해 다음과 같이 구성했다.

  • AttackMontage

Montage 내에서 Section을 통해 모션을 구분했으며 두 애니메이션의 연속된 동작으로 구성하였다.

  • Animation Sequence

DropDown 모션이 시작될 때와 Enemy가 떨어지는 시점에서 Notify를 추가하였다. 이는 DropDown 공격으로 인해 플레이어가 피해를 입는 범위를 나타낼 Actor를 소환할 것이다.

  • BP_DropDown

Actor는 단순히 Cylinder를 납작하게 생성해두었다. 매우 얉은 두께이기에 Collision의 영향은 없겠으나 CollisionType도 NoCollision으로 바꿔준다.

Actor의 EventGraph에서는 Actor가 생성되면 Timeline을 통해 크기를 키워주었다. 해당 크기는 공격범위와 동일하게 설정하였으며 Z값은 그대로 두어 사방으로 퍼지는 형태를 만들어주었다.

  • Notify_SpawnActor

공격이 시작될 때와 떨어지는 시점에서 발생하는 Notify는 위에서 만들어 둔 Actor를 생성하고 없애는 역할을 한다.

  • Notify_RadialDamage
#include "AnimNotify_RadialDamage.h"
#include "MainEnemy.h"

void UAnimNotify_RadialDamage::Notify(USkeletalMeshComponent* MeshComp, UAnimSequenceBase* Animation)
{
	UE_LOG(LogTemp, Warning, TEXT("notify"));
	if (MeshComp && MeshComp->GetOwner()) {
		AMainEnemy* Enemy = Cast<AMainEnemy>(MeshComp->GetOwner());
		if (Enemy) {
			Enemy->RadialDamage();
		}
	}
}

Enemy가 떨어지는 시점에 호출되는 RadialDamage Notify는 Enemy 클래스에 있는 RadialDamage()함수를 호출한다.

  • MainEnemy_RadialDamage
void AMainEnemy::RadialDamage()
{
	FVector Center = this->GetActorLocation();
	TArray<FOverlapResult> OverlapResults;
	FCollisionQueryParams CollisionQueryParam(NAME_None, false, this);

	bool bResult = GetWorld()->OverlapMultiByChannel(
		OverlapResults,
		Center,
		FQuat::Identity,
		ECollisionChannel::ECC_EnemyAttack,
		FCollisionShape::MakeSphere(1000),
		CollisionQueryParam
	);

	if (bResult) {
		for (auto OverlapResult : OverlapResults) {
			APlayerCharacter* Player = Cast<APlayerCharacter>(OverlapResult.GetActor());
			if (Player && Player->GetOwner()->ActorHasTag("Player")) {
				UGameplayStatics::ApplyRadialDamage(GetWorld(), damage, this->GetActorLocation(), 1000, nullptr, TArray<AActor*>(), this, GetController(), false, ECC_EnemyAttack);
				DrawDebugSphere(GetWorld(), Center, 1000, 16, FColor::Green, false, 3.0f);
			}
			else {
				DrawDebugSphere(GetWorld(), Center, 1000, 16, FColor::Red, false, 3.0f);
			}
		}
	}
}

RadialDamage()함수는 Enemy를 중점으로 지정한 범위에 모든 Player에게 데미지를 입힌다. CollisionChannel을 따로 만들어서 Player를 제외한 모든 클래스들은 Ignore로 지정해두었다.

0개의 댓글