Gameplay Effect (게임플레이 이펙트)는 GAS에서 어트리뷰트를 변경하기 위한 방법이다. Base Value
와 Current Value
로 나뉘어 있고, 데미지를 입히거나 체력을 회복시키는 등 단발성의 이펙트, 일정 시간 (또는 영구히) 동안 어트리뷰트를 변화시키는 시간 개념이 존재하는 이펙트 등을 모두 포함한다.
어트리뷰트의 'Base Value'를 영구히 변화시킨다.
remove 되거나 undo 될 일이 없는 변화는 Base Value, 일정 시간 후 사라지는 등 remove되는 종류의 변화는 Current Value의 변화를 발생시킨다. 이 둘의 차이는 중요하다.
일정 시간동안 어트리뷰트의 Current Value
를 변화시킨다. 일정 시간이 지나면 자동으로 소멸한다.
Duration과 비슷하지만, 직접 제거하지 않는 한 영구히 지속되는 Current Value
의 변화이다.
시간에 따라 주기적으로 적용되는 Base Value
의 변화이다. 일회성이 아니라 여러 번 적용된다는 점에서는 Instant과 구분되지만, 일정 시간이 걸린다는 점에서 Duration과 혼동하지 않아야 한다.
예를 들어 초당 마나를 얼마씩 재생한다거나, 일정 시간동안 동작을 하지 않으면 스태미너가 서서히 차오르는 등의 변화이다.
https://github.com/tranek/GASDocumentation?tab=readme-ov-file#concepts-ge-spec
GameplayEffect Spec(GESpec)은 게임플레이 이펙트의 인스턴스처럼 생각할 수 있다. 게임플레이 이펙트는 런타임보다 이전에 생성되어야 하지만 Spec은 런타임에도 자유롭게 생성되고 수정될 수 있다. 게임플레이 이펙트를 적용할 때, 이펙트로부터 스펙이 생성되고, 바로 이 스펙이 실제 타겟에 적용된다.
GESpec의 내용 중 주목할만한 것에는 다음과 같은 것들이 있다:
GameplayEffect
클래스https://github.com/tranek/GASDocumentation?tab=readme-ov-file#concepts-ge-context
Gameplay Effect Context는 GESpec의 instigator와 Target Data를 가지고 있다. context는 또한 ModifierMagnitudeCalculation, GameplayEffectExecutionCalculation, AttributeSet 등의 사이에 임의의 데이터를 전달하는 데 서브클래스로서 사용할 수 있는 좋은 장소이다.
void AAuraEffectActor::ApplyEffectToTarget(AActor* Target, TSubclassOf<UGameplayEffect> GameplayEffectClass)
{
UAbilitySystemComponent* TargetASC = UAbilitySystemBlueprintLibrary::GetAbilitySystemComponent(Target);
if (TargetASC == nullptr)
{
return;
}
check(GameplayEffectClass);
FGameplayEffectContextHandle EffectContextHandle = TargetASC->MakeEffectContext();
EffectContextHandle.AddSourceObject(this);
const FGameplayEffectSpecHandle EffectSpecHandle = TargetASC->MakeOutgoingSpec(GameplayEffectClass, ActorLevel, EffectContextHandle);
const FActiveGameplayEffectHandle ActiveEffectHandle = TargetASC->ApplyGameplayEffectSpecToSelf(*EffectSpecHandle.Data.Get());
}
FGameplayEffectContextHandle
: Effect를 관리할 수 있는 핸들. .Get()
함수를 통해 컨텍스트에 접근할 수 있다.MakeOutgoingSpec
: 컨텍스트의 액터들에게 줄 effect를 GameplayEffectClass에 해당하는 서브클래스로 지정해서 Spec을 만든다. (이 Spec을 실제 Apply에 사용할 것)ApplyGameplayEffectSpecToSelf
: GameplayEffect를 적용. ApplyGameplayEffect
를 사용하지 않고 Spec이 붙은 것을 사용하면 SpecHandle을 먼저 만들어서 세부 사항을 변경한 후 이를 사용할 수 있기 때문에 복잡한 효과를 적용할 때 좋다.반면 ApplyGameplayEffect
함수는 GameplayEffect를 인스턴스화해서 즉시 적용시킨다. 간단한 사용을 위해 설계되었다.
GameplayEffect는 기본적으로는 Spec에 의해 각각의 인스턴스로 존재 및 적용된다. GameplayEffect에 스택을 사용할 수 있으며, Stack limit count
를 설정함으로써 동시에 적용될 수 있는 이펙트의 개수를 조절할 수 있다.
스택 카운트 개념을 사용할 주체가 이펙트를 가하는 쪽인지, 아니면 이펙트가 가해지는 쪽인지에 따라 Aggregate by source/target으로 구분할 수 있다.
그 중에서 source는 이펙트를 가하는 쪽에서 최대 스택 카운트 개념을 사용하겠다는 것이다. 예를 들어 stack limit count가 2로 설정되어 있다면 그 주체는 다른 타겟에게 이펙트를 최대 두 번만 적용할 수 있다.
한편 그 타겟은 다른 주체로부터는 이펙트를 받을 수 있다. 각 주체별로 별도의 타겟 카운트를 사용하기 때문이다.
반면 이펙트가 가해지는, 즉 주체가 아닌 객체 측에서 스택 카운트를 설정할 수도 있다. 어떤 주체로부터 이펙트를 받는지의 여부를 막론하고, 객체가 최대로 받을 수 있는 이펙트의 개수를 제한한다.