PART 4 - 강의 5/8

GameplayEffect 설계

버프, 디버프, 데미지 시스템의 핵심

01

GameplayEffect 개요

속성 수정의 세 가지 지속 유형

Duration Policy 설명 사용 사례
Instant 즉시 적용 후 종료 데미지, 힐, 스탯 초기화
Duration 지정 시간 동안 유지 버프, 디버프, DoT
Infinite 수동 제거까지 유지 패시브, 장비 효과
Blueprint에서 GameplayEffect 생성 // Content Browser에서 생성 Content Browser > Add > Blueprint Class > GameplayEffect // 주요 설정 항목 Duration Policy: Instant / HasDuration / Infinite Duration Magnitude: 지속 시간 (HasDuration일 때) Period: 주기적 적용 간격 Modifiers: 속성 수정 목록 Executions: 커스텀 계산 클래스 Gameplay Cues: 시각/청각 효과 Tags: 이펙트 관련 태그
02

Modifier 구성

속성 수정 방법과 연산

Modifier Op 연산 예시
Add 값 더하기 체력 +50
Multiply 값 곱하기 공격력 x1.5
Divide 값 나누기 이동속도 /2
Override 값 덮어쓰기 MaxHealth = 200
Modifier Magnitude 타입 // Scalable Float // 고정 값 또는 Curve Table 사용 Magnitude Calculation Type: Scalable Float Scalable Float Magnitude: 50.0 // Attribute Based // 다른 속성 값 기반 Magnitude Calculation Type: Attribute Based Backing Attribute: AttackPower Attribute Capture: Source Coefficient: 1.5 // AttackPower * 1.5 // Set By Caller // 런타임에 동적으로 설정 Magnitude Calculation Type: Set By Caller Data Tag: Data.Damage // Custom Calculation // C++ 클래스로 복잡한 계산 Magnitude Calculation Type: Custom Calculation Class Calculation Class: UMyDamageCalculation
03

SetByCaller 활용

동적 이펙트 값 설정

C++ // GameplayEffect 적용 시 SetByCaller 값 설정 void ApplyDamageEffect(UAbilitySystemComponent* TargetASC, TSubclassOf<UGameplayEffect> DamageEffectClass, float DamageAmount) { if (!TargetASC || !DamageEffectClass) { return; } // 이펙트 컨텍스트 생성 FGameplayEffectContextHandle Context = TargetASC->MakeEffectContext(); Context.AddSourceObject(this); // 이펙트 스펙 생성 FGameplayEffectSpecHandle Spec = TargetASC->MakeOutgoingSpec( DamageEffectClass, 1, // 레벨 Context ); if (Spec.IsValid()) { // SetByCaller로 데미지 값 설정 // GameplayEffect에서 Data.Damage 태그로 참조 Spec.Data->SetSetByCallerMagnitude( FGameplayTag::RequestGameplayTag(FName("Data.Damage")), DamageAmount ); // 이펙트 적용 TargetASC->ApplyGameplayEffectSpecToSelf(*Spec.Data.Get()); } } // GameplayAbility에서 사용 void UMyAttackAbility::ApplyDamage(AActor* Target) { float FinalDamage = BaseDamage * GetAbilityLevel(); // 크리티컬 계산 if (FMath::FRand() < CriticalChance) { FinalDamage *= CriticalMultiplier; } UAbilitySystemComponent* TargetASC = UAbilitySystemBlueprintLibrary::GetAbilitySystemComponent(Target); if (TargetASC) { FGameplayEffectSpecHandle SpecHandle = MakeOutgoingGameplayEffectSpec(DamageEffectClass, GetAbilityLevel()); SpecHandle.Data->SetSetByCallerMagnitude( FGameplayTag::RequestGameplayTag(FName("Data.Damage")), FinalDamage ); ApplyGameplayEffectSpecToTarget( CurrentSpecHandle, CurrentActorInfo, CurrentActivationInfo, SpecHandle, TargetASC ); } }
04

Stacking 설정

중첩 효과 관리

Stacking 옵션 // Stacking Type None // 중첩 없음, 새 효과가 기존 대체 AggregateBySource // 소스별로 스택 관리 AggregateByTarget // 타겟에서 통합 스택 // Stack Limit Count // 최대 스택 수 (예: 5) // Stack Duration Refresh Policy RefreshOnSuccessfulApplication // 스택 추가 시 지속시간 갱신 NeverRefresh // 지속시간 갱신 안 함 // Stack Period Reset Policy ResetOnSuccessfulApplication // 스택 추가 시 주기 리셋 NeverReset // 주기 리셋 안 함 // Overflow Effects // 최대 스택 초과 시 적용할 다른 이펙트

독 스택 예시

AggregateByTarget, 최대 5스택, 스택마다 초당 데미지 증가

버프 갱신 예시

AggregateBySource, RefreshOnApplication으로 지속시간 연장

05

쿨다운 및 비용

어빌리티 제한 시스템

Cooldown GameplayEffect // GE_Cooldown_Fireball (Blueprint) Duration Policy: HasDuration Duration Magnitude: 5.0 // 5초 쿨다운 // Granted Tags (이펙트 활성 시 부여) Tags to Add: - Cooldown.Ability.Fireball // GameplayAbility에서 설정 Cooldown Gameplay Effect Class: GE_Cooldown_Fireball // 쿨다운 태그 확인 Cooldown Tags: - Cooldown.Ability.Fireball
Cost GameplayEffect // GE_Cost_Fireball (Blueprint) Duration Policy: Instant // Modifiers [0] Attribute: Mana Modifier Op: Add Magnitude: -30 // 마나 30 소모 // GameplayAbility에서 설정 Cost Gameplay Effect Class: GE_Cost_Fireball // 비용 검사는 CanActivateAbility에서 자동 수행
C++ 쿨다운 조회 // 남은 쿨다운 시간 확인 float GetCooldownTimeRemaining(UAbilitySystemComponent* ASC, FGameplayTag CooldownTag) { if (!ASC) return 0.0f; FGameplayTagContainer CooldownTags; CooldownTags.AddTag(CooldownTag); // 활성화된 쿨다운 이펙트들 가져오기 FGameplayEffectQuery Query = FGameplayEffectQuery::MakeQuery_MatchAnyOwningTags(CooldownTags); TArray<float> Durations = ASC->GetActiveEffectsTimeRemaining(Query); if (Durations.Num() > 0) { // 가장 긴 남은 시간 반환 Durations.Sort([](float A, float B) { return A > B; }); return Durations[0]; } return 0.0f; }
SUMMARY

핵심 요약

  • 세 가지 Duration: Instant(즉시), Duration(시간제한), Infinite(무한)
  • Modifier로 속성 값 수정 (Add, Multiply, Override)
  • SetByCaller로 런타임에 동적 값 전달
  • Stacking으로 버프/디버프 중첩 관리
  • Cooldown/Cost Effect로 어빌리티 사용 제한
PRACTICE

도전 과제

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

실습 1: 즉시 데미지 Effect 구현

UGameplayEffect를 상속하여 GE_Damage를 만들고, Duration Policy를 Instant로 설정하세요. Modifier에서 Health Attribute를 Additive로 감소시키고, Execution Calculation으로 방어력 계산을 적용하세요.

실습 2: Duration/Infinite Effect로 버프 구현

GE_AttackBuff(Duration=10초, AttackPower +20%)와 GE_Poison(Infinite, 매 1초마다 Health -5)을 구현하세요. Period와 Stacking Policy를 설정하여 중복 적용 규칙을 정의하세요.

심화 과제: GameplayCue 연동

GameplayEffect에 GameplayCue(GC_HitImpact, GC_BuffActive, GC_Heal)를 연결하세요. UGameplayCueNotify_Static과 AGameplayCueNotify_Actor를 구현하여 시각/사운드 피드백을 제공하세요.