PART 5 - 강의 1/2

GameplayCue 타입별 활용

시각/청각 피드백 시스템

01

GameplayCue 개요

시각/청각 피드백 분리

GameplayCue는 게임플레이 로직과 시각/청각 피드백을 분리하는 시스템입니다. 이를 통해 서버에서는 로직만, 클라이언트에서는 이펙트만 처리하여 네트워크 효율성을 높입니다.

GameplayCue의 장점
  • 분리된 책임 - 게임플레이 로직과 피드백 분리
  • 네트워크 효율 - 서버는 로직, 클라이언트는 이펙트
  • 재사용성 - 여러 어빌리티에서 같은 Cue 사용 가능
  • 에디터 통합 - 블루프린트에서 쉽게 구성
02

Static vs Actor Cue

두 가지 Cue 타입

GameplayCue 타입 비교 // 1. GameplayCueNotify_Static (기본 클래스) // - 인스턴스 없이 CDO에서 직접 실행 // - 가볍고 빠름, 상태 저장 불가 // - 파티클, 사운드 한 번 재생에 적합 UCLASS() class UGC_BurstEffect : public UGameplayCueNotify_Static { GENERATED_BODY() public: virtual bool OnExecute_Implementation( AActor* Target, const FGameplayCueParameters& Parameters) const override { // 파티클 스폰 if (BurstParticle) { UNiagaraFunctionLibrary::SpawnSystemAtLocation( Target->GetWorld(), BurstParticle, Parameters.Location); } // 사운드 재생 if (BurstSound) { UGameplayStatics::PlaySoundAtLocation( Target, BurstSound, Parameters.Location); } return true; } protected: UPROPERTY(EditDefaultsOnly) UNiagaraSystem* BurstParticle; UPROPERTY(EditDefaultsOnly) USoundBase* BurstSound; };
Actor 기반 Cue // 2. AGameplayCueNotify_Actor // - 월드에 Actor로 스폰 // - 상태 저장 가능, 지속 효과에 적합 // - 버프 아이콘, 지속 파티클 등 UCLASS() class AGC_BurningEffect : public AGameplayCueNotify_Actor { GENERATED_BODY() public: // 지속 효과 시작 virtual bool OnActive_Implementation( AActor* Target, const FGameplayCueParameters& Parameters) override { AttachToActor(Target, FAttachmentTransformRules::SnapToTargetNotIncludingScale); if (FireParticleComponent) { FireParticleComponent->Activate(); } return true; } // 지속 효과 종료 virtual bool OnRemove_Implementation( AActor* Target, const FGameplayCueParameters& Parameters) override { if (FireParticleComponent) { FireParticleComponent->Deactivate(); } // Actor 제거 예약 SetLifeSpan(2.0f); return true; } protected: UPROPERTY(VisibleAnywhere) UNiagaraComponent* FireParticleComponent; };
타입 인스턴스 상태 용도
Static CDO 사용 불가 일회성 효과
Actor Actor 스폰 가능 지속 효과
03

Cue 이벤트 타입

OnExecute, OnActive, OnRemove, WhileActive

Cue 이벤트 종류 // GameplayCue 이벤트 타입 enum class EGameplayCueEvent : uint8 { // 즉시 실행 (Instant GameplayEffect) OnExecute, // 지속 효과 시작 (Duration/Infinite Effect) OnActive, // 지속 효과 종료 OnRemove, // 매 틱마다 (Actor Cue만) WhileActive }; // Actor Cue에서 WhileActive 활용 virtual bool WhileActive_Implementation( AActor* Target, const FGameplayCueParameters& Parameters) override { // 스택 카운트에 따른 이펙트 강도 조절 float Intensity = Parameters.RawMagnitude; if (FireParticleComponent) { FireParticleComponent->SetFloatParameter( FName("Intensity"), Intensity); } return true; }
Cue 이벤트 선택

OnExecute는 Instant Effect에, OnActive/OnRemove는 Duration/Infinite Effect에 사용됩니다. WhileActive는 Actor Cue에서만 매 틱 호출됩니다.

04

Cue 호출 방법

Effect와 수동 호출

GameplayCue 호출 방법 // 방법 1: GameplayEffect에서 자동 호출 // Blueprint에서 GameplayEffect의 GameplayCue Tags 배열에 태그 추가 // GameplayCue.Damage.Fire 등 // 방법 2: C++에서 수동 호출 void UGA_FireBall::ActivateAbility(...) { // 즉시 실행 Cue FGameplayCueParameters CueParams; CueParams.Location = GetAvatarActorFromActorInfo()->GetActorLocation(); CueParams.Normal = GetAvatarActorFromActorInfo()->GetActorForwardVector(); CueParams.RawMagnitude = 1.0f; // Execute (일회성) K2_ExecuteGameplayCue( FGameplayTag::RequestGameplayTag(FName("GameplayCue.Ability.FireBall.Launch")), CueParams); } // 지속 Cue 추가/제거 void UGA_BurningDebuff::ApplyBurning() { FGameplayCueParameters CueParams; CueParams.RawMagnitude = StackCount; // Add (지속 효과 시작) K2_AddGameplayCue( FGameplayTag::RequestGameplayTag(FName("GameplayCue.Status.Burning")), CueParams); } void UGA_BurningDebuff::RemoveBurning() { // Remove (지속 효과 종료) K2_RemoveGameplayCue( FGameplayTag::RequestGameplayTag(FName("GameplayCue.Status.Burning"))); }
05

Cue Parameters

Cue에 데이터 전달

FGameplayCueParameters 구조체 struct FGameplayCueParameters { // 월드 위치 FVector Location; // 노말 방향 FVector Normal; // Effect Context (소스/타겟 정보) FGameplayEffectContextHandle EffectContext; // 소스 오브젝트 TWeakObjectPtr<UObject> SourceObject; // 물리 머터리얼 TWeakObjectPtr<UPhysicalMaterial> PhysicalMaterial; // 원본 수치 (스택 카운트 등) float RawMagnitude; // 정규화된 수치 (0~1) float NormalizedMagnitude; // GameplayEffect Level float AbilityLevel; }; // 커스텀 데이터 전달 void PassCustomDataToCue() { FGameplayCueParameters CueParams; // EffectContext를 통한 커스텀 데이터 전달 FGameplayEffectContextHandle ContextHandle = AbilitySystemComponent->MakeEffectContext(); // 커스텀 Context 사용 시 FMyGameplayEffectContext* MyContext = static_cast<FMyGameplayEffectContext*>(ContextHandle.Get()); MyContext->SetCustomData(MyData); CueParams.EffectContext = ContextHandle; CueParams.RawMagnitude = DamageAmount; K2_ExecuteGameplayCue(CueTag, CueParams); }
SUMMARY

핵심 요약

  • Static Cue: CDO 사용, 일회성 효과 (파티클, 사운드)
  • Actor Cue: Actor 스폰, 지속 효과 (버프 이펙트)
  • OnExecute: Instant Effect, OnActive/OnRemove: Duration Effect
  • K2_ExecuteGameplayCue: 일회성, K2_AddGameplayCue: 지속 시작
  • FGameplayCueParameters로 위치, 강도 등 데이터 전달
PRACTICE

도전 과제

배운 내용을 직접 실습해보세요

실습 1: Static vs Actor Cue

GameplayCue.Hit (Static, 일회성)과 GameplayCue.Buff.Fire (Actor, 지속) 각각을 구현하세요. UGameplayCueNotify_Static에서 파티클 스폰, AGameplayCueNotify_Actor에서 루프 이펙트를 재생하세요.

실습 2: Cue Parameters 활용

FGameplayCueParameters의 Location, Normal, EffectContext를 사용하여 히트 위치에 정확히 이펙트를 배치하세요. PhysicalMaterial에 따라 다른 이펙트를 선택하세요.

심화 과제

undefined