[UE5] GAS Gameplay Effect에 대해

kkado·2024년 8월 23일
0

UE5

목록 보기
59/63
post-thumbnail

Gameplay Effect

Gameplay Effect (게임플레이 이펙트)는 GAS에서 어트리뷰트를 변경하기 위한 방법이다. Base ValueCurrent Value로 나뉘어 있고, 데미지를 입히거나 체력을 회복시키는 등 단발성의 이펙트, 일정 시간 (또는 영구히) 동안 어트리뷰트를 변화시키는 시간 개념이 존재하는 이펙트 등을 모두 포함한다.

주요 프로퍼티

  • Duration : Duration(기간)에 따라 즉시, 또는 일정 시간 동안 유지되는 어트리뷰트 변화인지를 나타내는 프로퍼티
  • Modifier : 모디파이어는 이펙트가 어트리뷰트를 어떤 식으로 변화시킬 것인지를 나타낸다. 어트리뷰트에 특정한 값을 더하거나, 곱하거나, 나눌 수 있고 새 값으로 설정할 수도 있다. 또한 '20만큼' 과 같은 Scalable Float 값으로 설정한다거나, '최대 체력의 5%만큼' 등 다른 어트리뷰트와의 연산을 통해 설정할 수 있다.

종류

Instant

어트리뷰트의 'Base Value'를 영구히 변화시킨다.

remove 되거나 undo 될 일이 없는 변화는 Base Value, 일정 시간 후 사라지는 등 remove되는 종류의 변화는 Current Value의 변화를 발생시킨다. 이 둘의 차이는 중요하다.

Duration

일정 시간동안 어트리뷰트의 Current Value를 변화시킨다. 일정 시간이 지나면 자동으로 소멸한다.

Infinite

Duration과 비슷하지만, 직접 제거하지 않는 한 영구히 지속되는 Current Value의 변화이다.

Periodic

시간에 따라 주기적으로 적용되는 Base Value의 변화이다. 일회성이 아니라 여러 번 적용된다는 점에서는 Instant과 구분되지만, 일정 시간이 걸린다는 점에서 Duration과 혼동하지 않아야 한다.

예를 들어 초당 마나를 얼마씩 재생한다거나, 일정 시간동안 동작을 하지 않으면 스태미너가 서서히 차오르는 등의 변화이다.

Gameplay Effect Spec

https://github.com/tranek/GASDocumentation?tab=readme-ov-file#concepts-ge-spec

GameplayEffect Spec(GESpec)은 게임플레이 이펙트의 인스턴스처럼 생각할 수 있다. 게임플레이 이펙트는 런타임보다 이전에 생성되어야 하지만 Spec은 런타임에도 자유롭게 생성되고 수정될 수 있다. 게임플레이 이펙트를 적용할 때, 이펙트로부터 스펙이 생성되고, 바로 이 스펙이 실제 타겟에 적용된다.

GESpec의 내용 중 주목할만한 것에는 다음과 같은 것들이 있다:

  • Spec이 만들어진 GameplayEffect 클래스
  • Spec의 duration. 기본적으로는 Effect와 동일하지만, 달라질 수도 있다.
  • Spec의 level. 기본적으로는 Spec을 생성한 레벨이지만 달라질 수도 있다.
  • Spec의 current stack count. stack limit은 Effect에서 가지고 있다.

Gameplay Effect Context

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를 인스턴스화해서 즉시 적용시킨다. 간단한 사용을 위해 설계되었다.

Stacking

GameplayEffect는 기본적으로는 Spec에 의해 각각의 인스턴스로 존재 및 적용된다. GameplayEffect에 스택을 사용할 수 있으며, Stack limit count를 설정함으로써 동시에 적용될 수 있는 이펙트의 개수를 조절할 수 있다.

Aggregate by source

스택 카운트 개념을 사용할 주체가 이펙트를 가하는 쪽인지, 아니면 이펙트가 가해지는 쪽인지에 따라 Aggregate by source/target으로 구분할 수 있다.

그 중에서 source는 이펙트를 가하는 쪽에서 최대 스택 카운트 개념을 사용하겠다는 것이다. 예를 들어 stack limit count가 2로 설정되어 있다면 그 주체는 다른 타겟에게 이펙트를 최대 두 번만 적용할 수 있다.

한편 그 타겟은 다른 주체로부터는 이펙트를 받을 수 있다. 각 주체별로 별도의 타겟 카운트를 사용하기 때문이다.

Aggregate by target

반면 이펙트가 가해지는, 즉 주체가 아닌 객체 측에서 스택 카운트를 설정할 수도 있다. 어떤 주체로부터 이펙트를 받는지의 여부를 막론하고, 객체가 최대로 받을 수 있는 이펙트의 개수를 제한한다.

profile
베이비 게임 개발자

0개의 댓글