๐ ์ ๋ฐ๋ฏธ GAS ๊ฐ์ ์ค ๊ธฐ๋กํด๋๊ณ ์ถ์ ๋ด์ฉ์ ์ ์ด๋ ํฌ์คํธ
Section 5 : Gameplay Effect

UObject ํด๋์ค๋ฅผ ์์๋ฐ์ ๋ฐ์ดํฐ ํด๋์ค์ด๋ค.
Attribute์ GameplayTag๋ฅผ ์์ ํ ๋ ์ฌ์ฉํ๋ค.
Modifier : ๊ฐ ์์
Execution : ๊ฐ ์์ ๋ฟ ์๋๊ณ ์ฝ๋๋ฅผ ์ถ๊ฐํด์ ํน์ ์ก์
์ํ ๊ฐ๋ฅ

GameplayEffect
์ ์ ์ ์
์์ฑ ๋ณ๊ฒฝ, ์ง์ ์๊ฐ, ์ฃผ๊ธฐ, ํ๊ทธ, ๊ทธ๋ฆฌ๊ณ ์กฐ๊ฑด๋ถ ๋
ผ๋ฆฌ ๋ฑ์ ์ค์ ํด ๋์ ์ค๊ณ๋
ํน์ํ ์ํฉ ๊ตฌํ์ ์ํด ์๋ธํด๋์ค๋ฅผ ๋ง๋๋ ๋์ Exectuion์ด๋ Modifier๋ฅผ ํ์ฉํ๊ธฐ
GameplayEffectSpec
๋ฐํ์์ ์์ฑ๋๋ ์ธ์คํด์ค
FGameplayEffectSpec ๊ตฌ์กฐ์ฒด๋ก ์กด์ฌ
ํน์ GameplayEffect๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ๊ตฌ์ฒด์ ์ธ ์์น, ์ ์ฉ ๋์, ๋ ๋ฒจ ๋ฑ์ ํฌํจํด์ ๋ง๋ค์ด์ง
๊ด๊ณ
GameplayEffect๋ฅผ ๋ง๋ ๋ค.
๊ฒ์ ์ค ๋ฅ๋ ฅ์ด ๋ฐ๋๋๋ฉด ์ฝ๋์์ MakeOutgoingSpec() ๊ฐ์ ํจ์๋ฅผ ์จ์ GameplayEffectSpec์ ์์ฑํ๋ค.
์ด GameplayEffectSpec์ด ApplyGameplayEffectSpecToTarget() ๋ฑ์ ํจ์๋ก ํ๊ฒ์๊ฒ ์ ์ฉ๋๋ค.
์ ์ฉ ์์
void AAuraEffectActor::ApplyEffectToTarget(AActor* TargetActor, TSubclassOf<UGameplayEffect> GameplayEffectClass)
{
// UAbilitySystemBlueprintLibrary::GetAbilitySystemComponent ์ฌ์ฉํ๋ฉด ASC ๋ถ๋ฌ์ฌ ์ ์์
// ๋ด๋ถ ์ฝ๋๋ฅผ ๋ณด๋ฉด
// 1. IAbilitySystemInterface ์์ ๋ฐ์ ๊ฒฝ์ฐ : ์ธํฐํ์ด์ค ๊ตฌํ ํจ์๋ก ๋ถ๋ฌ์ด
// 2. ๋ฐ์ง ์์ ๊ฒฝ์ฐ : AbilitySystemComponent๋ฅผ ์ฐพ์์ ๋ถ๋ฌ์ค๋ 2๊ฐ์ง ๊ฒฝ์ฐ ๋ชจ๋ ๋์ํจ
UAbilitySystemComponent* TargetASC = UAbilitySystemBlueprintLibrary::GetAbilitySystemComponent(TargetActor);
if (TargetASC == nullptr)
{
return;
}
check(GameplayEffectClass);
// FGameplayEffectContextHandle ๋ง๋ค๊ธฐ
FGameplayEffectContextHandle EffectContextHandle = TargetASC->MakeEffectContext();
// Context์๋ ๋ค์ํ ์ ๋ณด๊ฐ ๋ค์ด๊ฐ๊ณ Handle์ Wrapper ํด๋์ค์
// EffectContext์ ์ ๋ณด ์ถ๊ฐ (์ด ์ดํํธ๋ฅผ ๋ฐ์์ํจ ๊ฐ์ฒด ์ถ๊ฐํ ๊ฒ)
EffectContextHandle.AddSourceObject(this);
// FGameplayEffectSpec ๋ง๋ค๊ธฐ
FGameplayEffectSpecHandle EffectSpecHandle = TargetASC->MakeOutgoingSpec(GameplayEffectClass,ActorLevel,EffectContextHandle);
// ApplyGameplayEffect~~ ์ข
๋ฅ ์ฌ๋ฌ๊ฐ์ง ์์
// ์ธ์๋ก EffectSpec ์ฐธ์กฐ ํฌ์ธํฐ๊ฐ ํ์ํ๋ฐ EffectSpecHandle์ ๋ํผ์ด๊ณ ๊ทธ ์์๋ Data(SharedPtr)๊ฐ ๋ค์ด์์
// SharedPtr ์์ฒด๋ ๋ํผ์ด๋ฏ๋ก Getํ๋ฉด ํฌ์ธํฐ๊ฐ ๋์ด
// ํฌ์ธํฐ๊ฐ ์๋ ๊ทธ ์ฐธ์กฐ๊ฐ ์์ฒด๊ฐ ํ์ํ๋ฏ๋ก * ๋ฅผ ๋ถ์ฌ์ค
FActiveGameplayEffectHandle ActiveGameplayEffectHandle = TargetASC->ApplyGameplayEffectSpecToSelf(*EffectSpecHandle.Data.Get());
}
ApplyGameplayEffectSpecToTarget()์ FActiveGameplayEffectHandle์ ๋ฆฌํดํ๋ค.

GameplayEffect์ DurationPolicy๋ ํฌ๊ฒ ์ธ๊ฐ์ง
Instant
AttributeData์ BaseValue๋ฅผ ์ฆ๊ฐ์ ์ผ๋ก ์์
Duration
AttributeData์ CurrentValue๋ฅผ ํน์ ์๊ฐ๋์ ์์
-> ์๊ฐ์ด ์ง๋๋ฉด BaseValue๋ก ๋์์จ๋ค.
ex) 5์ด๊ฐ ๋ฐฉ์ด๋ ฅ์ด 100 ์ฆ๊ฐํ๋ ๊ฒฝ์ฐ (๊ธฐ์กด 10)
Inifinite
AttributeData์ CurrentValue๋ฅผ ํน์ ์๊ฐ๋์ ์์
-> ์๊ฐ์ด ์ง๋๋ฉด BaseValue๋ก ๋์์จ๋ค.
ex) ๋ฐฉ์ด๋ ฅ์ด 100 ์ฆ๊ฐํ๋ ๊ฒฝ์ฐ (๊ธฐ์กด 10)
FActiveGameplayEffectHandle ํ์ฉ)// Remove ์ธ์์ -1 (๊ธฐ๋ณธ๊ฐ) ๋ฃ์ผ๋ฉด ๋ชจ๋ ์คํ์ด ์ ๊ฑฐ๋จ
ASC->RemoveActiveGameplayEffect(ActiveGameplayEffectHandle,1); // 1๊ฐ๋ง ์ ๊ฑฐ
Periodic
Duration, Infinite์๋ง ์ ์ฉ
ํน์ ๊ธฐ๊ฐ๋์ ์ ์ฉ๋๋ ์ดํํธ์ n์ด๋ง๋ค ์ดํํธ๊ฐ ๋ฐ๋ํ๋๋ก ํด์ค๋ค.
BaseValue์ ์ง์ ์ํฅ์ ์ค๋ค.
CurrentValue ์์ ํ ๋์์ค๋ ๋ฐฉ์์ด ์๋๊ธฐ๋๋ฌธ์ ์ดํํธ๊ฐ ํ๋ ค๋ ๊ธฐ์กด๊ฐ์ผ๋ก ๋์์ค์ง ์์ex) 2์ด๋์ ์ด 20์ ์ฒด๋ ฅ ํ๋ณต์ ํ๋ ๊ฒฝ์ฐ (Period๋ 0.1์ด ๊ฐ๊ฒฉ)

Duration : 2์ดPeriod : 0.1Modifier : Add , 1ํ๋ฒ์ ์ ์ฉ๋๋ ์ดํํธ์ ์๋ฅผ ์ ํํ ์ ์๋ค.
Stacking Type
bySource : ๊ฐ์ ํ๊ฒ์ด์ด๋ ์์ค๊ฐ ๋ค๋ฅด๋ฉด ์ดํํธ ์คํ ๋ฐ๋ก ๊ณ์ฐ

byTarget : ๊ฐ์ ํ๊ฒ์ด๋ผ๋ฉด ์์ค๊ฐ ๋ฌ๋ผ๋ ์คํ์ ํฉ์ณ์ ๊ณ์ฐ

์ดํํธ ์ ์ฉ ์ ๊ฐ ํด๋จํํ ๋ ์ฌ์ฉ (๋ค๋ฅธ ํจ์ ํธ์ถ์ด๋ ๊ธฐ๋ฅ์ ํ์ง ์์ ๊ฒ ๊ถ์ฅ)
์ค๋ฒ๋ผ์ด๋ํด์ ์ฌ์ฉ
virtual void PreAttributeChange(const FGameplayAttribute& Attribute, float& NewValue) override;
.
.
.
void UAuraAttributeSet::PreAttributeChange(const FGameplayAttribute& Attribute, float& NewValue)
{
Super::PreAttributeChange(Attribute, NewValue);
// Accessor ๋งคํฌ๋ก ์ฌ์ฉํด์ ์ํ๋ Attribute์ ์ ์ฉ
if (Attribute == GetHealthAttribute())
{
// NewValue๋ฅผ ์์
NewValue = FMath::Clamp(NewValue, 0.f , GetMaxHealth());
}
}
์ดํํธ ์ ์ฉ ์ ์ ํธ์ถ๋๋ ๊ฒ์ด๊ธฐ ๋๋ฌธ์ ์ด ์ดํ ๋จ๊ณ์์ ๊ฐ ์์ ์ด ์ผ์ด๋๋ค๋ฉด
์ต์ข
์ ์ผ๋ก๋ ํด๋จํ ๋ฒ์๋ฅผ ๋์ด๊ฐ ์๋ ์์ผ๋ฏ๋ก ์ฃผ์ ํ์.
๊ฒ์ํ๋ ์ด ์ดํํธ ์คํ ํ ํธ์ถ๋๋ ํจ์๋ก Data๋ฅผ ํตํด ์ฐ๊ด๋ ๋๋ถ๋ถ์ ์ํฐํฐ์ ์ ๊ทผ ๊ฐ๋ฅํจ
์ค๋ฒ๋ผ์ด๋ํด์ ์ฌ์ฉ
virtual void PostGameplayEffectExecute(const struct FGameplayEffectModCallbackData& Data) override;
.
.
.
void UAuraAttributeSet::PostGameplayEffectExecute(const struct FGameplayEffectModCallbackData& Data)
{
Super::PostGameplayEffectExecute(Data);
// EffectContextHandle
EffectContextHandle = Data.EffectSpec.GetContext();
// Source์ AbilitySystemComponent ๋ฐ์์ค๊ธฐ
SourceASC = Props.EffectContextHandle.GetOriginalInstigatorAbilitySystemComponent();
// SourceASC๋ฅผ ํตํด AvatarActor, Controller ๋ฑ์ ์ ๊ทผ ๊ฐ๋ฅ
// Target์ ์กํฐ ์ ๋ณด์๋ ์ ๊ทผ ๊ฐ๋ฅ
if (Data.Target.AbilityActorInfo.IsValid() && Data.Target.AbilityActorInfo->AvatarActor.IsValid())
{
// Target์ AvatarActor์, ASC๋ฑ์ ์ ๊ทผ
TargetAvatarActor = Data.Target.AbilityActorInfo->AvatarActor.Get();
TargetController = Data.Target.AbilityActorInfo->PlayerController.Get();
TargetCharacter = Cast<ACharacter>(Props.TargetAvatarActor);
TargetASC = UAbilitySystemBlueprintLibrary::GetAbilitySystemComponent(Props.TargetAvatarActor);
}
}
FGameplayEffectModCallbackData๋ฅผ ํตํด ๋ค์ํ ์ ๋ณด์ ์ ๊ทผํ๊ณ ์ํ๋ ์์
์ ์ํํ ์ ์๋ค.
GameplayEffect BP์์ ๋ ๋ฒจ์ ๋ฐ๋ฅธ Magnitude ๊ฐ ์ ์ฉ์ ์ํด ์ปค๋ธํ
์ด๋ธ์ ์ฌ์ฉํ ์ ์๋ค.


float ๊ฐ * ์ปค๋ธ ๋ด์ level์ ํ ๋น๋ ๊ฐ์ด ๊ณฑํด์ ธ์ ์ ์ฉ๋จ
ex) 1 * HealingCurve Level 1 ๊ฐ 5.f ์ธ 5๊ฐ ์ ์ฉ๋จ (Preview At 1 : 5.000)
GameplayEffectSpec์ ๋ง๋ค ๋ ๋ ๋ฒจ ๋ฃ์ด์ค
// FGameplayEffectSpec ๋ง๋ค๊ธฐ
TargetASC->MakeOutgoingSpec(GameplayEffectClass,ActorLevel,EffectContextHandle);
https://github.com/jongmin7759/Unreal_GAS/commit/f3b3cfe6533cc40d1eec12ff70f2d76a282be4f3
https://github.com/jongmin7759/Unreal_GAS/commit/69c7bbe7bd815cefe911d6076443df6f378537d1