๐ฎ 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; };IWeaponInterface์์ ํผ๊ฒฉ ์ ๋ฐ๋ฏธ์ง๋ฅผ ์ฃผ๊ฑฐ๋, ํผ๊ฒฉ ์ ๋๋ฉ์ด์ ์ ์๋ ์ํฌ ํจ์ OnHitActor()์ ๊ณต๊ฒฉ ์ข ๋ฃ๋ฅผ ์๋ฆฌ๋ AttackEnd()ํจ์๋ฅผ ์ถ๊ฐํ์๋ค.
๐ฎ AWeaponBase.h
UCLASS() class BOSSFIGHT_API AWeaponBase : public APropBase, public IWeaponInterface { GENERATED_BODY() // ์ค๋ต protected: // ์ค๋ต AActor* HitedActor; };์ดํ AWeaponBase์ ์ธํฐํ์ด์ค์์ ์ ์ํ ํจ์์, AActor ํฌ์ธํฐํ์ ํผ๊ฒฉ๋ ๊ฐ์ฒด๋ฅผ ์ ์ฅํ ๋ณ์๋ฅผ ์ถ๊ฐ ํ์๋ค.
AttackEnd() ํจ์๋ ๋จ์ํ๊ฒ HitedActor๋ฅผ nullptr๋ก ๋ณ๊ฒฝ ํด์ฃผ๋๋ก ๊ตฌํ ํ์๋ค.
๐ฎ APlayerWeapon.h
UCLASS() class BOSSFIGHT_API APlayerWeapon : public AWeaponBase { GENERATED_BODY() // ์ค๋ต virtual void OnHitActor(AActor* HitActor) override; virtual void OnHitActor(AActor* HitActor, int32 PartNum); };๐ฎ APlayerWeapon.cpp
void APlayerWeapon::AttackTrace() { // ์ค๋ต if (HitResult.GetActor() && HitResult.GetComponent()) { if (UBFCombetBoxComponent* HitComponent = Cast<UBFCombetBoxComponent>(HitResult.GetComponent())) { if (HitComponent->GetPartNum() != 0) { OnHitActor(HitResult.GetActor(), HitComponent->GetPartNum()); } else if (HitComponent->GetPartNum() == 0) { OnHitActor(HitResult.GetActor()); } } } } void APlayerWeapon::OnHitActor(AActor* HitActor) { if (HitedActor == HitActor) { return; } HitedActor = HitActor; FGameplayEventData Data; Data.Instigator = GetOwner(); Data.Target = HitActor; UAbilitySystemBlueprintLibrary::SendGameplayEventToActor(GetOwner(), BFGameplayTag::Shared_Event_OnDamaged, Data); } void APlayerWeapon::OnHitActor(AActor* HitActor, int32 PartNum) { if (HitedActor == HitActor) { return; } HitedActor = HitActor; FGameplayEventData Data; Data.Instigator = GetOwner(); Data.Target = HitActor; switch (PartNum) { case 1: UAbilitySystemBlueprintLibrary::SendGameplayEventToActor(GetOwner(), BFGameplayTag::Shared_Event_OnDamaged_Part1, Data); break; case 2: UAbilitySystemBlueprintLibrary::SendGameplayEventToActor(GetOwner(), BFGameplayTag::Shared_Event_OnDamaged_Part2, Data); break; default: break; } }๋ค์์ผ๋ก APlayerWeapon์์ OnHitActor() ํจ์๋ฅผ ๊ตฌํ ํด์ฃผ์๋ค. ์ด๋ ์ ์บ๋ฆญํฐ๋ ๋ถ์ํ๊ดด๋ฅผ ์ํด BoxComponent์ PartNum์ด ๋ถ์ฌ ๋์ด ์๊ธฐ์ ํด๋น PartNum์ ๋ฐ๋ผ OnHitActor()๋ฅผ ๋ค๋ฅด๊ฒ ์ ์ฉ ํ๊ธฐ์ํด ์ค๋ฒ๋ก๋ฉ์ ํ์๋ค.
OnHitActor()ํจ์๋ Trace์ค ์ฒ์์ผ๋ก ํผ๊ฒฉ๋ ์๊ฐ ์๋ ํ๋ฉฐ, ์ค๋ณต์ผ๋ก ์๋๋๋ ๊ฒ์ ๋ฐฉ์ง ํ๋๋ก ์ฝ๋๋ฅผ ์์ฑ ํ์๋ค.
๋ํ FGameplayEventData๋ฅผ ํตํด Instigator์ Target์ ์ง์ ํด์ฃผ์๊ณ . UAbilitySystemBlueprintLibrary::SendGameplayEventToActor()๋ฅผ ํตํด Gameplay Event๋ฅผ ๋ฐ์ก ํ๋๋ก ๊ตฌํ ํ์๋ค.



void AEnemyWeapon::AttackTrace() { //์ค๋ต WeaponCollision->SetCollisionResponseToChannel(ECC_Pawn, ECR_Ignore); //์ค๋ต if (HitResult.GetActor() && UBFFunctionLibrary::IsTargetPawnHostile(Cast<APawn>(GetOwner()), Cast<APawn>(HitResult.GetActor()))) { OnHitActor(HitResult.GetActor()); } } void AEnemyWeapon::OnHitActor(AActor* HitActor) { if (HitedActor == HitActor) { return; } HitedActor = HitActor; if (UBFFunctionLibrary::NativeDoseActorHaveTag(HitedActor, BFGameplayTag::Player_Status_Avoiding)) { return; } FGameplayEventData Data; Data.Instigator = GetOwner(); Data.Target = HitActor; // TODO : ๊ฐ ๊ณต๊ฒฉ, ์ฝ๊ณต๊ฒฉ์ Tag๋ฅผ ํตํด ๊ตฌ๋ถํ์ฌ, SendGameplayEventToActor() ๋ฐ์ก ํ๋๋ก ๊ตฌํ UAbilitySystemBlueprintLibrary::SendGameplayEventToActor(GetOwner(), BFGameplayTag::Shared_Event_OnDamaged, Data); } void AEnemyWeapon::AttackEnd() { Super::AttackEnd(); WeaponCollision->SetCollisionResponseToChannel(ECC_Pawn, ECR_Block); }๊ธฐ๋ณธ์ ์ผ๋ก ํ๋ ์ด์ด์ ๋์ผํ ๋ฐฉ์์ด๋ค. ๋ค๋ง, ์ ๊ณต๊ฒฉ์ ์ Collision์ ์ถฉ๋ํ์ฌ ํ๋ ์ด์ด ์บ๋ฆญํฐ๊ฐ ๋ฐ๋ ค๋๋ ๊ฒ์ ๋ฐฉ์ง ํ๊ธฐ์ํด SetCollisionResponseToChannel()์ ํตํด, Pawn์ ๋ฐ์์ ์ผ์์ ์ผ๋ก ๋ฌด์ํ๋๋ก ํ์๋ค.
๋ํ ์ดํ ์ ์บ๋ฆญํฐ์ ๊ณต๊ฒฉ์๋ํ ํผ๊ฒฉ ์ ๋๋ฉ์ด์ ์ ๊ตฌ๋ถ ํ๋๋ก TODO๋ฆฌ์คํธ๋ฅผ ์์ฑ ํ์๋ค.
์ถ๊ฐ์ ์ผ๋ก ํ๋ ์ด์ด๊ฐ ํํผ ์ค์ด๋ฉด, GameplayEvent๋ฅผ ๋ฐ์ก ํ์ง ์๋๋ก ๊ตฌํ ํ์๋ค.
