
UGameplayModMagnitudeCalculation (MMC)는 언리얼 엔진의 Gameplay Ability System(GAS) 프레임워크에서 Attribute의 Modifier를 적용할때 커스텀 계산식을 사용하기 위해 쓰입니다. 이번 글에서는 MMC의 구조와 사용법, 그리고 레벨 기반 커스텀 계산식을 구현한 예제를 소개합니다.
MMC(UGameplayModMagnitudeCalculation)는 GameplayEffect의 효과 크기(Magnitude)를 동적으로 계산하는 데 사용됩니다. 이는 단순히 기본값이나 계수를 설정하는 방식보다 유연하며, 다음과 같은 계산을 수행할 수 있습니다.
활력, 지능에 따라 체력과 마나량이 달라지지만 거기에 더해 플레이어의 레벨도 체력양과 마나량에 영향을 주도록 만들고자 했습니다.
MMC는 다음과 같은 메서드를 오버라이드하여 커스텀 계산식을 정의합니다.
virtual float CalculateBaseMagnitude_Implementation(const FGameplayEffectSpec& Spec) const override;
Spec 객체는 GameplayEffect 실행에 필요한 데이터와 태그를 포함합니다.다음은 Intelligence 속성과 플레이어 레벨을 기반으로 마나 최대치(Max Mana)를 계산하는 예제입니다.
#pragma once
#include "CoreMinimal.h"
#include "GameplayModMagnitudeCalculation.h"
#include "MMC_MaxMana.generated.h"
UCLASS()
class YOURGAME_API UMMC_MaxMana : public UGameplayModMagnitudeCalculation
{
GENERATED_BODY()
public:
UMMC_MaxMana();
protected:
virtual float CalculateBaseMagnitude_Implementation(const FGameplayEffectSpec& Spec) const override;
private:
FAggregatorCaptureDefinition IntelligenceDefinition;
};
#include "MMC_MaxMana.h"
#include "YourAttributeSet.h"
#include "CombatInterface.h"
float UMMC_MaxMana::CalculateBaseMagnitude_Implementation(const FGameplayEffectSpec& Spec) const
{
// 1. 소스 및 타겟 태그 가져오기
const FGameplayTagContainer* SourceTags = Spec.CapturedSourceTags.GetAggregatedTags();
const FGameplayTagContainer* TargetTags = Spec.CapturedTargetTags.GetAggregatedTags();
// 2. 계산 매개변수 설정
FAggregatorEvaluateParameters EvaluateParams;
EvaluateParams.SourceTags = SourceTags;
EvaluateParams.TargetTags = TargetTags;
// 3. Intelligence 속성 캡처 및 초기화
float Intelligence = 0.0f;
GetCapturedAttributeMagnitude(IntelligenceDefinition, Spec, EvaluateParams, Intelligence);
Intelligence = FMath::Max<float>(Intelligence, 0.0f);
// 4. CombatInterface를 통해 플레이어 레벨 가져오기
ICombatInterface* CombatInterface = Cast<ICombatInterface>(Spec.GetContext().GetSourceObject());
const int32 PlayerLevel = CombatInterface ? CombatInterface->GetPlayerLevel() : 1; // 기본 레벨 1
// 5. 계산식 적용: 기본값 + Intelligence + PlayerLevel
return 50 + 2.5f * Intelligence + 10.f * PlayerLevel;
}
MMC는 GameplayEffect 실행 시 관련 속성을 캡처하여 계산에 사용합니다.
float Intelligence = 0.0f;
GetCapturedAttributeMagnitude(IntelligenceDefinition, Spec, EvaluateParams, Intelligence);
IntelligenceDefinition: 캡처할 속성을 정의한 객체.Spec: GameplayEffect의 실행 맥락(Context) 데이터를 포함.EvaluateParams: 소스와 타겟 태그를 포함한 매개변수.Spec.GetContext().GetSourceObject()를 사용하여 소스 객체에서 데이터를 추출합니다.
ICombatInterface* CombatInterface = Cast<ICombatInterface>(Spec.GetContext().GetSourceObject());
const int32 PlayerLevel = CombatInterface ? CombatInterface->GetPlayerLevel() : 1;
CombatInterface는 인터페이스를 통해 플레이어 레벨 데이터를 제공합니다.1을 반환합니다.기본값(40), Intelligence 기반 값(1.25배), 레벨 기반 값(5배)을 조합하여 최종 결과를 반환합니다.
return 40 + 1.25f * Intelligence + 5.f * PlayerLevel;
MMC에서 속성을 캡처하기 위해 사용되는 FGameplayEffectAttributeCaptureDefinition에 대해 살펴봅시다.
USTRUCT(BlueprintType)
struct GAMEPLAYABILITIES_API FGameplayEffectAttributeCaptureDefinition
{
GENERATED_USTRUCT_BODY()
UPROPERTY(EditDefaultsOnly, Category=Capture)
FGameplayAttribute AttributeToCapture;
UPROPERTY(EditDefaultsOnly, Category=Capture)
EGameplayEffectAttributeCaptureSource AttributeSource;
UPROPERTY(EditDefaultsOnly, Category=Capture)
bool bSnapshot;
};
AttributeToCapture: 캡처할 속성(Attribute)을 정의.AttributeSource: 캡처 위치(Source/Target)를 지정.Source: 효과를 생성한 객체.Target: 효과를 받는 객체.bSnapshot: 속성의 스냅샷 여부를 설정.MMC는 UAbilitySystemComponent와 함께 작동하여 GameplayEffectSpec을 생성하고 적용합니다.
FGameplayEffectSpecHandle SpecHandle = AbilitySystemComponent->MakeOutgoingSpec(GameplayEffectClass, Level, Context);
MakeOutgoingSpec: GameplayEffectSpec를 생성합니다.Context: EffectContext 객체로, 소스 및 타겟 데이터를 포함합니다.MMC는 GAS의 Attribute Modifier의 계산식을 커스터마이징하는 데 유용한 도구입니다. Attribute 기반 계산, Tag와 데이터를 활용한 계산, 레벨 기반 추가 계산 등을 구현할 수 있습니다.