BossFight - 무기 페링 구현

김대겸·2025년 5월 19일

무기 페링 구현

이번에는 적공격에 플레이어의 공격을 겹치면, 패링이되는 시스템을 구현 해보자.

우선 WeaponCollision을 공격 시작 및 종료 시에 QueryOnly로 변경, 공격 종료시 NoCollision으로 되돌리는 기능을 구현 해보자. 이는 모든 무기에 공통적으로 적용 됨으로, IWeaponInterface에서 함수를 추가하고, WeaponBaseClass에서 구현 하면 된다.

🎮 IWeaponInterface.h

class BOSSFIGHT_API IWeaponInterface
{
	GENERATED_BODY()

	// Add interface functions to this class. This is the class that will be inherited to implement this interface.
public:
	virtual void AttackTrace() = 0;
	virtual void OnHitActor(AActor* HitActor) = 0;
	virtual void AttackEnd() = 0;
	virtual void AttackStart() = 0;
};

위와 같이 IWeaponInterface에 공격 시작을 알리는 AttackStart() 순수 가상함수를 작성 하였다.

🎮 AWeaponBase.cpp

void AWeaponBase::AttackEnd()
{
	HitedActor = nullptr;
	WeaponCollision->SetCollisionEnabled(ECollisionEnabled::NoCollision);
}

void AWeaponBase::AttackStart()
{
	WeaponCollision->SetCollisionEnabled(ECollisionEnabled::QueryOnly);
}

이후 AWeaponBase Class에서 위와 같이 SetCollisionEnabled()함수를 통해 Collision을 활성화 및 비활성화 하고 있다.

다음으로 Collision이 Overlap되었을때의 반응을 추가 해보자. 무기를 통한 페링은 플레이어만 가능 하기에, PlayerWeapon에서 구현 해보자.

🎮 APlayerWeapon.h

UCLASS()
class BOSSFIGHT_API APlayerWeapon : public AWeaponBase
{
	GENERATED_BODY()
    //중략
	UFUNCTION()
	void OnWeaponParryOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult);

protected:
	APlayerWeapon();
    //중략
};

🎮 APlayerWeapon.cpp

APlayerWeapon::APlayerWeapon()
{
	WeaponCollision->OnComponentBeginOverlap.AddDynamic(this, &APlayerWeapon::OnWeaponParryOverlap);
}

void APlayerWeapon::OnWeaponParryOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{
	UBFFunctionLibrary::AddGameplayTagToActorIfNone(GetOwner(), BFGameplayTag::Player_Status_ParrySuccess)	;
}

우선은 간단하게 Tag를 부착하고, 해당 Tag가 있으면 데미지를 받지 않도록 구현 해보자.

void AEnemyWeapon::OnHitActor(AActor* HitActor)
{
	if (HitedActor == HitActor) { return; }

	HitedActor = HitActor;
	if (UBFFunctionLibrary::NativeDoseActorHaveTag(HitedActor, BFGameplayTag::Player_Status_Avoiding)) { return; }
	if (UBFFunctionLibrary::NativeDoseActorHaveTag(HitedActor, BFGameplayTag::Player_Status_ParrySuccess)) { return; }
	FGameplayEventData Data;
	Data.Instigator = GetOwner();
	Data.Target = HitActor;

	UAbilitySystemBlueprintLibrary::SendGameplayEventToActor(GetOwner(), BFGameplayTag::Shared_Event_OnDamaged, Data);
	if (UBFFunctionLibrary::NativeDoseActorHaveTag(GetOwner(), BFGameplayTag::Enemy_Status_Attack_Normal))
	{
		UAbilitySystemBlueprintLibrary::SendGameplayEventToActor(HitedActor, BFGameplayTag::Player_Event_OnHit_Normal, FGameplayEventData());
	}
	else if (UBFFunctionLibrary::NativeDoseActorHaveTag(GetOwner(), BFGameplayTag::Enemy_Status_Attack_Power))
	{
		UAbilitySystemBlueprintLibrary::SendGameplayEventToActor(HitedActor, BFGameplayTag::Player_Event_OnHit_Power, FGameplayEventData());
	}
}

마지막으로 PawnCombetComponent에서 AttackStart()를 호출 할수있도록 함수를 구현 해보자.

🎮 UPawnCombetComponent.cpp

void UPawnCombetComponent::AttackStart(EBFEquipType Type)
{
	UPawnEquipmentComponent* EquipmentComponent = Cast<IPawnEquipmentInterface>(GetOwner())->GetPawnEquipmentComponent();
	IWeaponInterface* WeaponInterface = Cast<IWeaponInterface>(EquipmentComponent->GetCurrentWeapon(Type));
	WeaponInterface->AttackStart();
}

위의 함수는 BlueprintCallable로 구현 하였다.

AttackTrace를 호출하는 AnimNotifyState를 수정하고 테스트 해보았다.

테스트

추가로 PlayerWeapon Class에 AttackEnd()함수를 Override하여 공격 종료시 부착 되었던 Player_Status_ParrySuccess Tag를 제거 하도록 코드를 추가 하였다.

다음에는 페링 성공시 적 캐릭터의 반응을 구현 해볼 예정이다.

0개의 댓글