在虚幻引擎(Unreal Engine)的 Gameplay Ability System(GAS)中,UGameplayModMagnitudeCalculation 是用于动态计算 Gameplay Effect 的 Modifier 数值的核心类。通过继承该类并重写其关键接口,可以实现复杂的数值计算逻辑(如基于角色属性的动态加成)。以下是常用接口及用法的详细介绍:
作用:计算 Gameplay Effect 的实际数值(如伤害值、治疗效果等)。
用法:必须重写此函数,在其中定义数值计算逻辑。可以通过捕获属性(如力量、智力)或外部参数动态计算。
virtual float CalculateBaseMagnitude_Implementation(const FGameplayEffectSpec& Spec) const override;
参数说明:
示例代码:
// 示例:计算伤害值(基础伤害 + 力量属性 * 系数)
float UMyDamageCalculation::CalculateBaseMagnitude_Implementation(const FGameplayEffectSpec& Spec) const
{
// 1. 获取施法者的力量属性
float Strength = 0.f;
FGameplayEffectContextHandle Context = Spec.GetContext();
if (const UAbilitySystemComponent* SourceASC = Context.GetInstigatorAbilitySystemComponent())
{
// 从AttributeSet获取属性值
Strength = SourceASC->GetNumericAttribute(UMyAttributeSet::GetStrengthAttribute());
}
// 2. 从Effect参数中获取动态配置的系数(如通过SetByCaller传递)
float DamageMultiplier = Spec.GetSetByCallerMagnitude(FGameplayTag::RequestGameplayTag("Data.DamageMultiplier"));
// 3. 计算最终伤害
float BaseDamage = 10.f; // 基础值
return BaseDamage + Strength * DamageMultiplier;
}
作用:通过 FGameplayEffectAttributeCaptureDefinition 定义需要捕获的属性(如攻击力、护甲值),并在计算时获取这些属性的当前值。
步骤 1:声明属性捕获定义
在子类中声明需要捕获的属性,通常在构造函数中初始化。
// 头文件声明
UPROPERTY()
FGameplayEffectAttributeCaptureDefinition StrengthDef;
// 构造函数初始化
UMyDamageCalculation::UMyDamageCalculation()
{
// 捕获施法者的力量属性(Source为施法者,Target为受击者)
StrengthDef = FGameplayEffectAttributeCaptureDefinition(
UMyAttributeSet::GetStrengthAttribute(),
EGameplayEffectAttributeCaptureSource::Source,
true // 是否在Effect应用时捕获快照(Snapshot)
);
// 必须调用此函数注册捕获的Attribute
RelevantAttributesToCapture.Add(StrengthDef);
}
步骤 2:在计算中使用捕获的属性
通过 GetCapturedAttributeMagnitude 获取属性值。
float UMyDamageCalculation::CalculateBaseMagnitude_Implementation(const FGameplayEffectSpec& Spec) const
{
// 获取捕获的属性值
FAggregatorEvaluateParameters EvaluationParameters;
float Strength = 0.f;
GetCapturedAttributeMagnitude(StrengthDef, Spec, EvaluationParameters, Strength);
// ... 后续计算
}
GetSetByCallerMagnitude
获取通过 SetByCaller 传递的动态参数(如技能等级、外部配置的系数)。
GetEffectLevel
获取 Gameplay Effect 的等级(通常用于等级缩放)。
int32 EffectLevel = Spec.GetEffectLevel();
GetSourceTags 和 GetTargetTags
获取与 Effect 关联的标签,用于条件判断。
const FGameplayTagContainer* SourceTags = Spec.CapturedSourceTags.GetAggregatedTags();
if (SourceTags->HasTag(FGameplayTag::RequestGameplayTag("State.Buff.PowerUp")))
{
// 如果施法者有"PowerUp"状态,增加伤害
Damage *= 2.f;
}
// 自定义计算类:根据目标护甲值减少伤害
UCLASS()
class UArmorMitigationCalculation : public UGameplayModMagnitudeCalculation
{
GENERATED_BODY()
public:
UArmorMitigationCalculation();
// 声明捕获的属性(目标护甲)
FGameplayEffectAttributeCaptureDefinition ArmorDef;
virtual float CalculateBaseMagnitude_Implementation(const FGameplayEffectSpec& Spec) const override;
};
// 构造函数中初始化属性捕获
UArmorMitigationCalculation::UArmorMitigationCalculation()
{
ArmorDef = FGameplayEffectAttributeCaptureDefinition(
UMyAttributeSet::GetArmorAttribute(),
EGameplayEffectAttributeCaptureSource::Target,
false // 不捕获快照,实时获取护甲值
);
RelevantAttributesToCapture.Add(ArmorDef);
}
// 计算逻辑
float UArmorMitigationCalculation::CalculateBaseMagnitude_Implementation(const FGameplayEffectSpec& Spec) const
{
// 获取原始伤害(假设通过SetByCaller传递)
float BaseDamage = Spec.GetSetByCallerMagnitude(FGameplayTag::RequestGameplayTag("Data.Damage"));
// 获取目标护甲值
float TargetArmor = 0.f;
FAggregatorEvaluateParameters EvalParams;
GetCapturedAttributeMagnitude(ArmorDef, Spec, EvalParams, TargetArmor);
// 护甲减伤公式(示例:每点护甲减少1%伤害)
float Mitigation = FMath::Clamp(TargetArmor * 0.01f, 0.f, 0.7f); // 最多减少70%伤害
return BaseDamage * (1.f - Mitigation);
}
在蓝图中创建 Gameplay Effect,选择 Modifier Magnitude Calculation 为自定义的计算类。
通过灵活使用 UGameplayModMagnitudeCalculation,可以实现高度动态的游戏数值系统(如基于角色属性、装备、环境因素的伤害计算)。