GAS_14_피격 시 활성화 되는 GA_HitReact 구현

2025. 5. 10. 17:14·내배캠/GAS(Gameplay Ability System)

📌 Hit React_Ability 구현

1. Gameplay Tag 설정
2. HitReact 어빌리티 생성
3. 하위 Ability 생성
4. Anim Montage 생성
5. Ability 부여

위 순서대로 Hit React Ability를 구현해보자.

✅Gameplay Tag 설정

✔️ RPGGameplayTags

더보기

🔹 RPGGameplayTags.h

#pragma once

#include "NativeGameplayTags.h"

namespace RPGGameplayTags
{
	/** 생략 */
	
	/** Enemy Tags */
	RPG_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(Enemy_Ability_Melee); // 근거리 공격 추가
	RPG_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(Enemy_Ability_Ranged); // 원거리 공격 추가

	RPG_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(Enemy_Weapon);

	/** Shared Tags */
	RPG_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(Shared_Ability_HitReact); // HitReact 추가

	RPG_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(Shared_Event_MeleeHit);
	RPG_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(Shared_Event_HitReact); // HitReact Event추가

	RPG_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(Shared_SetByCaller_BaseDamage);

}

🔹 RPGGameplayTags.cpp

#include "RPGGameplayTags.h"

namespace RPGGameplayTags
{
	/** 생략 */

	/** Enemy Tags */
	UE_DEFINE_GAMEPLAY_TAG(Enemy_Ability_Melee, "Enemy.Ability.Melee");
	UE_DEFINE_GAMEPLAY_TAG(Enemy_Ability_Ranged, "Enemy.Ability.Ranged");

	UE_DEFINE_GAMEPLAY_TAG(Enemy_Weapon, "Enemy.Weapon");

	/** Shared Tags */
	UE_DEFINE_GAMEPLAY_TAG(Shared_Ability_HitReact, "Shared.Ability.HitReact");

	UE_DEFINE_GAMEPLAY_TAG(Shared_Event_MeleeHit, "Shared.Event.MeleeHit");
	UE_DEFINE_GAMEPLAY_TAG(Shared_Event_HitReact, "Shared.Event.HitReact");

	UE_DEFINE_GAMEPLAY_TAG(Shared_SetByCaller_BaseDamage, "Shared.SetByCaller.BaseDamage");
}

 

✅ HitReact Ability 구현

"RPGEnemyGameplayAbility"를 상속 받는 GameplayAbility BP 클래스를 생성한다.

 

다음과 같이 로직을 구현한다. FaceAttacker의 경우 Default 값을 true로 설정한다.

앞서 구현했던 Ability와 다른 점은"Event ActivateAbilityFromEvent" 노드를 사용해야 한다는 점이다.
해당 GA는 인풋으로 발동되는 Ability가 아닌 Event로 발동되는 Ability이다. 따라서 기존에 Light Attack과 Heavy Attack 관련 Ability를 발동시키는 조건이 다르다.

 

앞서 구현했던 GA를 상속 받은 "GA_Guardian" 클래스를 생성하고, HitReact Montage를 할당한다.
Tag Setting으로 HitReact Ability 발동 중에는 다른 모든 Ability를 취소하고 Block 처리한다.
Instancing Policy의 경우 피격이 전투 중 수시로 발생하기 때문에 InstancedPerExecution 처럼 매번 인스턴스를 생성/파괴하게 되면 성능 낭비가 커진다.
따라서 Actor로 설정해, 최초 Ability를 부여 했을 때 한 번만 인스턴스를 생성하도록 하고 이후 추가적인 피격 시 재활성화 되는 구조가 더 적합하다.

추가적으로 Ability Trigger에 Tag 설정을 진행한다.
공격자가 공격 Ability에서 이 Tag로 Event를 전달하면, Enemy가 이 이벤트 태그를 가지고 있다면 수신할 수 있게 된다.

 

✅ StartUpData에 GA_HitReact 할당

Enemy의 StartUpData에 Reactive Ability 배열이 선언되어있다. 해당 배열에 방금 생성했던 "GA_Guardian_HitReact"를 할당 해준다.

 

✅ 플레이어 공격 Ability에서 Target에게 Event 전달

현재 플레이어의 공격 Ability 클래스인데, 그래프가 복잡해 보여 데미지를 주는 로직을 함수화 시킬 것이다.
그리고 함수 내부에서 데미지를 성공적으로 적용시켰다면, HitReact Event를 피격 대상에게 전송시킴으로써 GA_HitReact가 활성화 되도록 구현할 것이다.

 

위와 같이 함수화 시켜 그래프를 정리하고, 함수 명을 "HandleApplayDamage"로 변경한다.

 

함수 내부에서 데미지 적용이 Successful이면 "Send Gameplay Event to Actor" 노드로 피격 대상에게 HitReact Event Tag를 전달한다.

 

🔔 GA_HitReact 테스트

정상적으로 피격 시, HitReact Animation이 나오는 것을 확인할 수 있었고, 플레이어 위치로 회전까지 정상 작동한다.

 

✅ 피격 시, 머터리얼 색상 변경

Material Function을 다음과 같이 구현한 뒤 이를 이용해, HitReact시 Material 색을 잠시 바꿨다가 다시 원래대로 돌리도록 한다.

 

Material Instance를 생성한다.

 

컨텐츠 브라우저에서 스켈레탈 메시를 선택한 후 Material Instance로 돌아와 뷰포트 우측 하단에 버튼을 클릭하면 프리뷰 상태로 작업할 수 있다.

 

HitFxSwitch 값을 1로 올려 어떤 색으로 표시할지 정한 후, 다시 0으로 맞춰놓고 저장한다.

 

Enemy의 SkeletalMesh에서 방금 만든 Material Instance로 설정해준다.

 

Hit React Ability에서 몽타주가 있을 경우와 없을 경우 모두 스켈레탈 메시에서 머터리얼의 Scalar 값을 조절해주었다.
Parameter 이름도 Material Instance에서 복사해서 정확하게 입력해주도록 한다.
마지막으로 Ability가 종료되면 다시 0의 값을 주어 원래 상태로 되돌린다.

 

🔔 피격 시, 머터리얼 변화 테스트

정상적으로 HitReact Ability가 활성화 되면, Material 색상이 변하는 것을 확인할 수 있다.

 

📌 타격 성공시 피드백 효과  구현

✅ 타격 성공 시, Pause 효과

* 싱글플레이 게임 전용 
플레이어의 공격이 적에게 적중하면 잠깐 월드의 시간을 미세하게 정지시켜 조금 더 다이내믹한 타격 피드백을 줄 수 있다.
다만 월드의 시간을 조정하는 것이기 때문에 멀티플레이에선 해당 Ability를 사용하면 안된다.

✔️ RPGGameplayTags

더보기

🔹 RPGGameplayTags.h

#pragma once

#include "NativeGameplayTags.h"

namespace RPGGameplayTags
{
	/** 생략 */

	/** Player Tags */
	RPG_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(Player_Ability_Equip_Axe);
	RPG_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(Player_Ability_Unequip_Axe);
	RPG_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(Player_Ability_Attack_Light_Axe);
	RPG_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(Player_Ability_Attack_Heavy_Axe);
	RPG_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(Player_Ability_HitPause); // 공격 성공시 Pause 태그 추가

	RPG_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(Player_Weapon_Axe);

	RPG_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(Player_Event_Equip_Axe);
	RPG_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(Player_Event_Unequip_Axe);
	RPG_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(Player_Event_HitPause); // 공격 성공시 Pause Event 태그 추가
}

🔹 RPGGameplayTags.h

#include "RPGGameplayTags.h"

namespace RPGGameplayTags
{
	/** 생략 */

	/** Player Tags */
	UE_DEFINE_GAMEPLAY_TAG(Player_Ability_Equip_Axe, "Player.Ability.Equip.Axe");
	UE_DEFINE_GAMEPLAY_TAG(Player_Ability_Unequip_Axe, "Player.Ability.Unequip.Axe");
	UE_DEFINE_GAMEPLAY_TAG(Player_Ability_Attack_Light_Axe, "Player.Ability.Attack.Light.Axe");
	UE_DEFINE_GAMEPLAY_TAG(Player_Ability_Attack_Heavy_Axe, "Player.Ability.Attack.Heavy.Axe");
	UE_DEFINE_GAMEPLAY_TAG(Player_Ability_HitPause, "Player.Ability.HitPause"); // 공격 성공시 Pause 태그 추가


	UE_DEFINE_GAMEPLAY_TAG(Player_Weapon_Axe, "Player.Weapon.Axe");

	UE_DEFINE_GAMEPLAY_TAG(Player_Event_Equip_Axe, "Player.Event.Equip.Axe");
	UE_DEFINE_GAMEPLAY_TAG(Player_Event_Unequip_Axe, "Player.Event.Unequip.Axe");
	UE_DEFINE_GAMEPLAY_TAG(Player_Event_HitPause, "Player.Event.HitPause"); // 공격 성공시 Pause Event 태그 추가
}

✔️ Gameplay Ability(HitPause) 구현

에디터에서 다음과 같이 "GA_Hero_HitPause"를 구현한다. 이로써 대상을 공격해서 피격처리가 되었을 때 다이나믹한 느낌을 만들어 낼 수 있다. 

하지만 구현부를 살펴보면 월드 전체의 시간 흐름을 조절하여 효과를 Hit 피드백을 주는 것이기 때문에, 싱글플레이에서는 괜찮지만 멀티플레이 게임에서는 해당 Ability를 사용하면 안된다.
멀티플레이에선 Custom Time Dilation 기능을 만들어 자신(로컬)에게만 Dilation을 주도록 설정하는 등 다른 방법으로 구현해야한다.

 

✔️ Ability 할당

Hero 캐릭터의 StartUpData에 방금 만든 Ability를 할당해준다.

 

✔️ Hit 처리 되었을 때, 이벤트 전송해 GA_HitPause 활성화 로직

void UHeroCombatComponent::OnHitTargetActor(AActor* HitActor)
{
	if (OverlappedActors.Contains(HitActor))
	{
		return;
	}

	OverlappedActors.AddUnique(HitActor);

	FGameplayEventData Data;
	Data.Instigator = GetOwningPawn();
	Data.Target = HitActor;

	UAbilitySystemBlueprintLibrary::SendGameplayEventToActor(
		GetOwningPawn(),
		RPGGameplayTags::Shared_Event_MeleeHit,
		Data
	);
	
    // Hit Pause Ability 발동 Event 전달
	UAbilitySystemBlueprintLibrary::SendGameplayEventToActor(
		GetOwningPawn(),
		RPGGameplayTags::Player_Event_HitPause,
		FGameplayEventData()
	);
}
이전에 무기에 오버랩 되면 델리게이트 호출로 OnHitTargetActor가 호출되도록 구현했었다.
해당 함수 내부에서 HitPause 어빌리티를 실행할 Event를 전송한다.

 

🔔 HitPause Ability 테스트 결과

공격이 Target에 적중되지 않으면 Ability가 발생하지 않고, Target에 적중되는 순간 아주 미세하게 Pause 효과를 주어 전투의 느낌을 더 다이내믹하게 느껴진다.

 

🔎CameraShake

추가적으로 HitPause에서 CameraShake를 주어 조금 더 역동적으로 전투 경험을 느끼게 할 수도 있다.

 

🔎사운드 정리

HitReaction Sound를 몽타주에 넣었을 때, 적이 한번에 여러 명이 피격당하면 소리가 그 수 만큼 재생되어 정신없는 사운드가 될 것이다.
Concurrency를 생성해 한 번에 1개의 사운드만 재생되도록 설정한다면 동시에 여러 명을 타격하더라도, 하나의 HitReact 사운드를 재생시킬 수 있다.

 

'내배캠 > GAS(Gameplay Ability System)' 카테고리의 다른 글

GAS_16_Death Ability 구현 및 캐릭터 사후처리  (1) 2025.05.10
GAS_15_GameplayCue로 타격 사운드 재생  (0) 2025.05.10
GAS_13_피격 대상에게 GameEffect 적용  (0) 2025.05.09
GAS_12_피격 판정  (0) 2025.05.09
GAS_11_Attribute와 GameplayEffect  (0) 2025.05.08
'내배캠/GAS(Gameplay Ability System)' 카테고리의 다른 글
  • GAS_16_Death Ability 구현 및 캐릭터 사후처리
  • GAS_15_GameplayCue로 타격 사운드 재생
  • GAS_13_피격 대상에게 GameEffect 적용
  • GAS_12_피격 판정
동그래님
동그래님
  • 동그래님
    개발자 동그래
    동그래님
  • 전체
    오늘
    어제
    • 분류 전체보기 (210)
      • 공부 (51)
        • Code Cata (50)
      • 내배캠 (151)
        • TIL (50)
        • C++ (37)
        • Unreal Engine (48)
        • GAS(Gameplay Ability System.. (16)
      • Project (7)
        • Gunfire Paragon (5)
        • Arena Fighters (1)
  • 블로그 메뉴

    • 링크

    • 공지사항

    • 인기 글

    • 태그

    • 최근 댓글

    • 최근 글

    • hELLO· Designed By정상우.v4.10.3
    동그래님
    GAS_14_피격 시 활성화 되는 GA_HitReact 구현
    상단으로

    티스토리툴바