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를 구현하여 시각/사운드 피드백을 제공하세요.