Melee Attack을 구현하는 방법은 다양하다. 이번 포스트에서는 fist에 collision component를 붙여 공격하는 법과 Trace를 사용하는 방법을 알아보자.
LeftBox->AttachToComponent(GetMesh(), AttachmentRules, "LeftFist");
RightBox->AttachToComponent(GetMesh(), AttachmentRules, "RightFist");
LeftBox->SetCollisionProfileName(TEXT("OverlapAll"));
RightBox->SetCollisionProfileName(TEXT("OverlapAll"));
LeftBox->OnComponentBeginOverlap.AddDynamic(this, &AMonsterBase::OnOverlapBegin);
RightBox->OnComponentBeginOverlap.AddDynamic(this, &AMonsterBase::OnOverlapBegin);
항상 주먹에 닿일 때 공격이 된다면 이상할 것이다. 그러니 공격시에만 콜리전을 활성화 시켜주자
LeftBox->SetGenerateOverlapEvents(true);
RightBox->SetGenerateOverlapEvents(true);
LeftBox->SetGenerateOverlapEvents(false);
RightBox->SetGenerateOverlapEvents(false);
나는 콤보 공격으로 구성했기 때문에 왼손으로 공격시엔 왼손 위치에 Trace를 생성하고 오른손으로 공격시엔 오른손 위치에 Trace를 생성해야 한다.
switch (FistIndex)
{
case 1:
FistLoc = GetMesh()->GetSocketLocation(FName("LeftFist"));
break;
case 0:
FistLoc = GetMesh()->GetSocketLocation(FName("RightFist"));
break;
}
SweepSingleByChannel
: Trace를 생성하는 함수FHitResult HitResult;
FCollisionQueryParams Params(NAME_None, false, this);
bool bResult = GetWorld()->SweepSingleByChannel(
HitResult,
FistLoc,
FistLoc+ 50.f,
FQuat::Identity,
ECollisionChannel::ECC_GameTraceChannel1,
FCollisionShape::MakeSphere(50.f),
Params
);
if (bResult)
{
if (HitResult.GetActor()->IsValidLowLevel())
{
FDamageEvent DamageEvent;
HitResult.GetActor()->TakeDamage(ChargedAttackDamage, DamageEvent, GetController(), this);
}
}
Trace가 생성되는 모양을 보고싶다면 DrawDebug로 똑같이 그려줘야된다. 좀 귀찮다.. 하는김에 결과에 따라 색도 변경해보자
FColor DrawColor = bResult ? FColor::Green : FColor::Red;
DrawDebugCapsule(
GetWorld(),
TargetLoc,
100.f,
100.f,
FRotationMatrix::MakeFromZ(GetActorForwardVector()).ToQuat(),
DrawColor,
false,
3.f);
멀리있는 플레이어에게 점프하여 공격하는 스킬을 구현하기 위해 필요한 기능을 생각해보자. 해당 위치로 이동하여 똑같이 Trace를 생성하면 된다.
MoveComponentTo
: Component를 원하는 위치로 이동해주는 함수TargetLoc
: player의 위치Rotation
: 몬스터가 Player를 바라보는 Rot로 설정(PlayerLoc-MonsterLoc) FLatentActionInfo Info;
Info.CallbackTarget = this;
UKismetSystemLibrary::MoveComponentTo(
GetCapsuleComponent(),
TargetLoc,
(Target->GetActorLocation() - GetActorLocation()).Rotation(),
true,
true,
0.35f,
false,
EMoveComponentAction::Type::Move,
Info);