内容纲要

在GAS中,GameplayEffect(简称GE)里面,在涉及到Magnitude的地方,针对Magnitude Calculation Type都会有一个选项“Set By Caller”,其本质,是把Magnitude的具体数值,交由开发者在代码中决定。
image.png
如果设置为“Set By Caller”,它都需要填写一个Data Tag,其本质是,在GameplayEffect实例中,它有一个字典"SetByCallerTagMagnitudes",其声明如下

TMap<FGameplayTag, float> SetByCallerTagMagnitudes;

在ApplyGameplayEffectSpecToOwner时,会有以下计算,本质就是在字典"SetByCallerTagMagnitudes"中获取Magnitude的值。

FActiveGameplayEffectHandle UAbilitySystemComponent::ApplyGameplayEffectSpecToSelf(const FGameplayEffectSpec &Spec, FPredictionKey PredictionKey)
{
    // ...
    AppliedEffect = ActiveGameplayEffects.ApplyGameplayEffectSpec(Spec, PredictionKey, bFoundExistingStackableGE);
}

FActiveGameplayEffect* FActiveGameplayEffectsContainer::ApplyGameplayEffectSpec(const FGameplayEffectSpec& Spec, FPredictionKey& InPredictionKey, bool& bFoundExistingStackableGE)
{
    // ...
    if (AppliedEffectSpec.AttemptCalculateDurationFromDef(DefCalcDuration))
    {
        AppliedEffectSpec.SetDuration(DefCalcDuration, false);
    }
}

bool FGameplayEffectSpec::AttemptCalculateDurationFromDef(OUT float& OutDefDuration) const
{
    else
    {
        // The last parameters (false, 1.f) are so that if SetByCaller hasn't been set yet, we don't warn and default
        // to 1.f. This is so that the rest of the system doesn't treat the effect as an instant effect. 1.f is arbitrary
        // and this makes it illegal to SetByCaller something into an instant effect.
        bCalculatedDuration = Def->DurationMagnitude.AttemptCalculateMagnitude(*this, OutDefDuration, false, 1.f);
    }

    return bCalculatedDuration;
}

bool FGameplayEffectModifierMagnitude::AttemptCalculateMagnitude(const FGameplayEffectSpec& InRelevantSpec, OUT float& OutCalculatedMagnitude, bool WarnIfSetByCallerFail, float DefaultSetbyCaller) const
{
            case EGameplayEffectMagnitudeCalculation::SetByCaller:
            {
                OutCalculatedMagnitude = InRelevantSpec.GetSetByCallerMagnitude(SetByCallerMagnitude.DataTag, WarnIfSetByCallerFail, DefaultSet
            }
}

float FGameplayEffectSpec::GetSetByCallerMagnitude(FGameplayTag DataTag, bool WarnIfNotFound, float DefaultIfNotFound) const
{
    float Magnitude = DefaultIfNotFound;
    const float* Ptr = nullptr;
    {
        Ptr = SetByCallerTagMagnitudes.Find(DataTag);
    }
    {
        Magnitude = *Ptr;
    }

    return Magnitude;
}

因为GE中有很多地方可以用到Set By Caller,所以就需要给Set By Caller的Magnitude一个Data Tag,用来区分不同的地方。它是在GE内部使用的Tag。

最后修改日期: 2024年4月9日

作者