Udemy Unreal - Gameplay Ability System - Top Down RPG (Section 7)

๊น€์ข…๋ฏผยท2025๋…„ 4์›” 25์ผ

Udemy Unreal - GAS

๋ชฉ๋ก ๋ณด๊ธฐ
7/7

๐Ÿ“– ์œ ๋ฐ๋ฏธ GAS ๊ฐ•์˜ ์ค‘ ๊ธฐ๋กํ•ด๋‘๊ณ  ์‹ถ์€ ๋‚ด์šฉ์„ ์ ์–ด๋‘” ํฌ์ŠคํŠธ

Section 7 : GameplayEffect Modifier


GameplayAttribute ์ดˆ๊ธฐํ™”

๋ฐ์ดํ„ฐ ํ…Œ์ด๋ธ” ํ™œ์šฉํ•˜๊ธฐ

AbilitySystemComponent์˜ AttributeTest ์นดํ…Œ๊ณ ๋ฆฌ์—์„œ
DefaultStartingData์— ๋ฐ์ดํ„ฐ ํ…Œ์ด๋ธ” ์ฑ„์šฐ๊ธฐ

AttributeMetaData Row๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐ์ดํ„ฐ ํ…Œ์ด๋ธ”์„ ๋งŒ๋“ค์–ด์„œ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค.

๐Ÿ–๏ธ RowName์€ ๋ฐ˜๋“œ์‹œ {AttributeSet ์ด๋ฆ„}.{Attribute ์ด๋ฆ„}์˜ ๊ตฌ์กฐ๋ฅผ ์ง€์ผœ์•ผํ•œ๋‹ค.
ex) AuraAttributeSet.Strength

BaseValue๋งŒ ํ™•์‹คํžˆ ์ฑ„์šฐ๋ฉด ๋˜๊ณ  ์ด์™ธ์˜ ๊ฐ’์€ ์Šคํƒ ์ œ์™ธํ•˜๊ณ ๋Š” ์ฐธ๊ณ ๋งŒ.
(ํ•ด๋‹น ๊ธฐ๋Šฅ ์ž์ฒด๊ฐ€ ํ”„๋กœํ† ํƒ€์ž…์ด๋ผ ๋งŽ์ด ์“ฐ์ด์ง€๋Š” ์•Š๊ณ  ํ›„์ˆ ํ•  ์ดํŽ™ํŠธ๋ฅผ ํ†ตํ•ด ์ดˆ๊ธฐํ™”ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋งŽ์ด ์“ด๋‹ค๊ณ  ํ•จ)


GameplayEffect ํ™œ์šฉํ•˜๊ธฐ

Attribute ์ดˆ๊ธฐํ™”๋ฅผ ์œ„ํ•œ ์ดํŽ™ํŠธ๋ฅผ ๋งŒ๋“ค์–ด์„œ ์บ๋ฆญํ„ฐ ์ดˆ๊ธฐํ™” ์‹œ์ ์— ์ดํŽ™ํŠธ ์ ์šฉํ•˜๊ธฐ

Primary Attribute๋Š” ์ •ํ•ด์ง„ ๊ฐ’์œผ๋กœ ์ดˆ๊ธฐํ™”ํ•˜๊ณ , ๊ทธ ์ž์ฒด๋กœ ๋‹ค๋ฅธ Attribute์— ์˜ํ–ฅ์„ ๋ฐ›์ง€ ์•Š๋Š” ๊ฐ’๋“ค์ด๊ธฐ ๋•Œ๋ฌธ์— Duration Policy : Instant๋กœ 1ํšŒ ์ดˆ๊ธฐํ™”ํ•ด์ค€๋‹ค.

๋ฐ˜๋ฉด Derived Attribute๋Š” ๋‹ค๋ฅธ ๊ฐ’์— ์˜ํ•ด ์˜ํ–ฅ์„ ๋ฐ›๊ธฐ ๋•Œ๋ฌธ์— ๋‹ค๋ฅธ ๊ฐ’ ๋ณ€ํ™”์— ๋Œ€์‘์ด ๊ฐ€๋Šฅํ•˜๋„๋ก Duration Policy : Infinite๋กœ ์„ค์ •ํ•ด์ค€๋‹ค.

  • ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๋‹ค๋ฅธ ๊ฐ’ ๋ณ€ํ™”์— ๋”ฐ๋ฅธ ์žฌ๊ณ„์‚ฐ ์ฒ˜๋ฆฌ๋ฅผ ๋”ฐ๋กœ ํ•ด์ค„ ํ•„์š”์—†์ด ์•Œ์•„์„œ ๊ฐฑ์‹ ๋จ
  • Infinite๋กœ ๊ณ„์† GameplayEffect๊ฐ€ ์‚ด์•„์žˆ๋Š” ์ƒํƒœ์ด๊ธฐ๋•Œ๋ฌธ

Modifier

์—ฐ์‚ฐ์ž ์ ์šฉ ์ˆœ์„œ


๐Ÿ–๏ธ ์—ฐ์‚ฐ์ž ์šฐ์„ ์ˆœ์œ„๊ฐ€ ์ ์šฉ๋˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ์ˆœ์ฐจ์ ์œผ๋กœ ๊ณ„์‚ฐ๋œ๋‹ค.


Calculation Type

Attribute Based

Backing Attribute์˜ ๊ฐ’์„ ๊ธฐ๋ฐ˜์œผ๋กœ ๊ณ„์‚ฐํ•œ๋‹ค.

๐Ÿ–๏ธ Coefficient , Pre , Post ์˜ ๊ณ„์‚ฐ ์ˆœ์„œ์— ์ฃผ์˜ํ•˜๊ธฐ

  • Pre๋ฅผ ๋”ํ•œ ๋’ค Coefficient๊ฐ€ ๊ณฑํ•ด์ง€๊ณ  ๊ทธ ๊ฐ’์— Post๋ฅผ ๋”ํ•ด์ค€๋‹ค.

Custom Calculation Class (MMC)

๐Ÿ‘ Attribute๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ์†Œ์Šค๋‚˜ ํƒ€๊ฒŸ์ด ๋“ค๊ณ  ์žˆ๋Š” ๋‹ค์–‘ํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ํ™œ์šฉํ•ด์„œ ๊ณ„์‚ฐ์ด ๊ฐ€๋Šฅํ•˜๋„๋ก ํ•ด์ค€๋‹ค.

UGameplayModMagnitudeCalculation ํด๋ž˜์Šค๋ฅผ ํ™œ์šฉํ•œ๋‹ค.

์ฒ˜์Œ C++ ํด๋ž˜์Šค๋ฅผ ์ƒ์„ฑํ•˜๋ฉด ์•„๋ฌด๊ฒƒ๋„ ์—†๋Š” ์ƒํƒœ์ด๋ฏ€๋กœ ๋‹ค์Œ ๊ณผ์ •์ด ํ•„์š”ํ•˜๋‹ค.

  1. ์ƒ์„ฑ์ž ๋งŒ๋“ค๊ธฐ
  2. ๊ณ„์‚ฐ ํ•จ์ˆ˜ CalculateBaseMagnitude_Implementation ์˜ค๋ฒ„๋ผ์ด๋“œ
  3. ํ•„์š”ํ•œ Attribute ์บก์ฒ˜(FGameplayEffectAttributeCaptureDefinition)
    3-1. ์ƒ์„ฑ์ž์—์„œ ACCESSOR ๋งคํฌ๋กœ ํ†ตํ•ด MyAttributeSet์— ๋งŒ๋“ค์–ด์ง„ ํ•จ์ˆ˜๋กœ ํ• ๋‹น AttributeToCapture - ์–ด๋–ค Attribute ์บก์ฒ˜ํ• ์ง€
    3-2. ํ•ด๋‹น Attribute๋ฅผ ์ดํŽ™ํŠธ์˜ Source์—์„œ ๋ฐ›์•„์˜ฌ์ง€, Target์—์„œ ๋ฐ›์•„์˜ฌ์ง€ ์ง€์ •
    3-3. ์Šค๋ƒ…์ƒท ์—ฌ๋ถ€ ์„ค์ •
  4. RelevantAttributesToCapture์— ์บก์ฒ˜ํ•  Attribute ์ถ”๊ฐ€ํ•˜๊ธฐ
  5. GetCapturedAttributeMagnitude๋กœ ์›ํ•˜๋Š” Attribute์˜ ๊ฐ’์„ ๋ฐ›์•„์˜ค๊ณ 
  6. ์›ํ•˜๋Š” ๊ฐ’์œผ๋กœ ์กฐ์ •ํ•œ ๋’ค CalculateBaseMagnitude_Implementation์˜ ๊ฒฐ๊ณผ๋กœ ๋ฆฌํ„ด

๐Ÿ“˜ MMC_MaxHealth.h

UCLASS()
class AURA_API UMMC_MaxHealth : public UGameplayModMagnitudeCalculation
{
	GENERATED_BODY()
public:
	// 1. ์ƒ์„ฑ์ž ๋งŒ๋“ค๊ธฐ
	UMMC_MaxHealth();
	// 2. ๊ณ„์‚ฐ ํ•จ์ˆ˜ ์˜ค๋ฒ„๋ผ์ด๋“œ
	virtual float CalculateBaseMagnitude_Implementation(const FGameplayEffectSpec& Spec) const override;

private:
	// 3. ์บก์ฒ˜๋ฅผ ์œ„ํ•œ ๋ฉค๋ฒ„ ์ถ”๊ฐ€
	FGameplayEffectAttributeCaptureDefinition VigorDef;
};

๐Ÿ“– MMC_MaxHealth.cpp

UMMC_MaxHealth::UMMC_MaxHealth()
{
	// 3-1. ํŠน์ • Attribute ์บก์ฒ˜
	VigorDef.AttributeToCapture = UAuraAttributeSet::GetVigorAttribute();
    // 3-2. Attribute Source ์ง€์ •
	// MaxHealth์˜ ๊ฒฝ์šฐ ํ”Œ๋ ˆ์ด์–ด ์บ๋ฆญํ„ฐ๊ฐ€ ์Šคํƒฏ ์ดˆ๊ธฐํ™”ํ•  ๋•Œ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์œผ๋ฏ€๋กœ Source == Target
	VigorDef.AttributeSource = EGameplayEffectAttributeCaptureSource::Target;
    // 3-3. ์Šค๋ƒ…์ƒท ์—ฌ๋ถ€ ์„ค์ •
	// Attribute์˜ ๊ธฐ์ค€์ ์„ ์–ด๋А ์‹œ๊ธฐ๋กœ ํ•  ๊ฒƒ์ธ๊ฐ€.
	// True : EffectSpec์ด ์ƒ์„ฑ๋˜์ž๋งˆ์ž , False : Effect์˜ ์ ์šฉ ์‹œ์ ์—
	VigorDef.bSnapshot = false;
	// 4. ๋ฆฌ์ŠคํŠธ์— Attribute ์ถ”๊ฐ€ํ•˜๊ธฐ
	RelevantAttributesToCapture.Add(VigorDef);
}

float UMMC_MaxHealth::CalculateBaseMagnitude_Implementation(const FGameplayEffectSpec& Spec) const
{

	// Source์™€ Target์˜ ํƒœ๊ทธ ์ •๋ณด ์ ‘๊ทผ ๊ฐ€๋Šฅ
	const FGameplayTagContainer* SourceTags = Spec.CapturedSourceTags.GetAggregatedTags();
	const FGameplayTagContainer* TargetTags = Spec.CapturedTargetTags.GetAggregatedTags();

	FAggregatorEvaluateParameters EvaluationParameters;
	EvaluationParameters.SourceTags = SourceTags;
	EvaluationParameters.TargetTags = TargetTags;

	// 5. ํ•„์š”ํ•œ Attribute์˜ ํ˜„์žฌ๊ฐ’ ๋ฐ›์•„์˜ค๊ธฐ
	// Vigor๋Š” OutParam
	float Vigor = 0.f;
	GetCapturedAttributeMagnitude(VigorDef,Spec,EvaluationParameters,Vigor);
	// ํด๋žจํ•‘ (0๋ณด๋‹ค ๋‚ฎ์•„์ง€์ง€ ์•Š๋„๋ก)
	Vigor = FMath::Max<float>(Vigor,0.f);

	// Source ์˜ค๋ธŒ์ ํŠธ ๋ฐ›์•„์˜ค๊ธฐ (์ด ๊ฒฝ์šฐ AuraCharacter์˜ ๋ ˆ๋ฒจ์„ ์•Œ์•„๋‚ด๊ธฐ ์œ„ํ•จ)
	ICombatInterface* CombatInterface = Cast<ICombatInterface>(Spec.GetContext().GetSourceObject());
	const int32 PlayerLevel = CombatInterface->GetCombatLevel();
	
    // 6. ์›ํ•˜๋Š” ๊ฐ’์œผ๋กœ ์กฐ์ •ํ•œ ๋’ค ๋ฆฌํ„ด
	return 80.f + 2.5f * Vigor + 10.f * PlayerLevel;
}

์ปค๋ฐ‹

https://github.com/jongmin7759/Unreal_GAS/commit/41a52805e8ed6f9b0e4d2cd34efe4a68461bf805

profile
์ •๋ฆฌ์™€ ๊ธฐ๋ก

0๊ฐœ์˜ ๋Œ“๊ธ€