Course contentsShow
← Unreal Engine Game Development
Lesson 641 of 8809. Gameplay Ability System (GAS)Free lesson

Handling Attribute Clamping for Derived Statistics

Implement complex logic to recalculate dependent attributes like movement speed based on current health or energy levels within the Attribute Set.

In this lesson, you will learn how to maintain gameplay balance by dynamically clamping derived attributes—such as movement speed—based on fluctuating primary stats like health or stamina.

The Problem of Interdependency

In GAS, attributes are rarely isolated. Often, you want a character’s performance to degrade as they take damage. For example, a character might move at 100% speed when healthy, but slow down to 50% speed once their Health drops below 25%. If you simply modify the MovementSpeed attribute directly, you risk breaking the logic or creating race conditions where the movement speed doesn't correctly update when health is restored.

Implementing Derived Logic in PostGameplayEffectExecute

To handle this, we utilize the PostGameplayEffectExecute function within our AttributeSet. Because derived statistics (like speed) often depend on the current state of primary attributes (like health), we need to ensure that whenever an effect modifies a primary attribute, we recalculate the dependent one and enforce strict clamping.

Consider this implementation pattern:

void UMyAttributeSet::PostGameplayEffectExecute(const FGameplayEffectModCallbackData& Data)
{
    Super::PostGameplayEffectExecute(Data);

    if (Data.EvaluatedData.Attribute == GetHealthAttribute())
    {
        // Calculate the impact on MovementSpeed based on health percentage
        float CurrentHealth = GetHealth();
        float MaxHealth = GetMaxHealth();
        float HealthPercentage = CurrentHealth / MaxHealth;

        // Logic: Slow movement speed if health is low
        float NewSpeed = (HealthPercentage < 0.25f) ? 300.0f : 600.0f;

        // Apply and clamp the result to valid bounds
        SetMovementSpeed(FMath::Clamp(NewSpeed, 0.0f, 600.0f));
    }
}

Why Clamping Matters

Clamping is vital here because gameplay effects might attempt to set an attribute to an extreme value (e.g., a "Berserker" buff might temporarily boost speed while a "Crippled" debuff lowers it). By wrapping your calculation in FMath::Clamp, you ensure that the MovementSpeed never enters an invalid state, such as becoming negative, which could cause physics errors or movement glitches in the Character Movement Component. Always recalculate your derived attributes after the primary source changes to maintain a "Single Source of Truth."

Key Takeaway: Use PostGameplayEffectExecute to reactively recalculate dependent attributes based on primary stat changes, and always use FMath::Clamp to ensure derived values remain within gameplay-safe boundaries.