ASC学习笔记0019:返回给定游戏属性的当前值,如果未找到该属性则返回零。

中文注释:UrealEngine-5.2.1源码-AbilitySystemComponent.h

学习内容:

cpp 复制代码
/**
	 * 返回给定游戏属性的当前值,如果未找到该属性则返回零。
	 * 注意:这不会考虑预测的游戏效果修饰符,因此客户端的值可能并不总是准确的。
	 *
	 * @param Attribute 要查询的游戏属性
	 * @param bFound 如果属性在此组件中存在则设置为true
	 */
	UFUNCTION(BlueprintPure, Category = "Gameplay Attributes")
	float GetGameplayAttributeValue(FGameplayAttribute Attribute, bool& bFound) const;

这是一个典型的Unreal Engine游戏属性系统(Gameplay Attributes System)中的函数声明。让我为您详细解释这个函数:

函数功能

  • 作用:查询特定游戏属性(如生命值、法力值、攻击力等)的当前数值

  • 返回值:属性的当前值(浮点数),如果属性不存在则返回0

  • 输出参数bFound 表示是否成功找到该属性

参数说明

  • FGameplayAttribute Attribute:要查询的游戏属性,通常通过宏定义如 UPROPERTY(BlueprintReadOnly, Category = "Attributes") 声明

  • bool& bFound:输出参数,表示属性是否存在

使用示例

cpp 复制代码
// 在C++中使用
bool bAttributeFound;
float CurrentHealth = AttributeComponent->GetGameplayAttributeValue( 
    UBaseAttributeSet::GetHealthAttribute(), 
    bAttributeFound 
);

if (bAttributeFound)
{
    // 处理健康值
    UE_LOG(LogTemp, Warning, TEXT("Current Health: %f"), CurrentHealth);
}

blueprint

bash 复制代码
// 在蓝图中使用
[Get Gameplay Attribute Value]
    Attribute: [Get Health Attribute] 
    bFound: (输出引脚,连接到Branch节点)
    Return Value: 连接到其他节点

重要注意事项

  1. 客户端准确性:如注释所述,这不考虑预测的效果修饰符,客户端值可能与服务器不同步

  2. 属性查找bFound 参数很重要,可以区分"属性值为0"和"属性不存在"的情况

  3. 性能考虑:频繁调用可能影响性能,建议缓存结果

典型应用场景

  • UI显示角色属性

  • 技能条件检查

  • 游戏逻辑决策

  • 调试和信息显示

这个函数是Gameplay Ability System (GAS) 中访问属性值的常用方法之一。

在实际项目中,GetGameplayAttributeValue 函数有广泛的应用场景。以下是一些具体的实际用例:

1. UI 显示和更新

HUD 组件中显示角色属性

cpp 复制代码
// 在HUD或Widget组件中
void UPlayerHUDWidget::UpdateHealthBar()
{
    bool bFound;
    float CurrentHealth = AbilitySystemComponent->GetGameplayAttributeValue(
        UBaseAttributeSet::GetHealthAttribute(), bFound);
    float MaxHealth = AbilitySystemComponent->GetGameplayAttributeValue(
        UBaseAttributeSet::GetMaxHealthAttribute(), bFound);
    
    if (bFound && HealthBar)
    {
        float HealthPercent = CurrentHealth / MaxHealth;
        HealthBar->SetPercent(HealthPercent);
    }
}

// 定时更新或使用委托绑定属性变化
void UPlayerHUDWidget::BindAttributeChanges()
{
    if (UAbilitySystemComponent* ASC = GetAbilitySystemComponent())
    {
        ASC->GetGameplayAttributeValueChangeDelegate(
            UBaseAttributeSet::GetHealthAttribute())
            .AddUObject(this, &UPlayerHUDWidget::OnHealthChanged);
    }
}
复制代码

2. 技能条件和消耗检查

技能释放前的条件验证

cpp 复制代码
bool UFireballAbility::CanActivateAbility(...) const
{
    if (!Super::CanActivateAbility(...)) return false;
    
    bool bFound;
    float CurrentMana = GetAbilitySystemComponentFromActorInfo()->GetGameplayAttributeValue(
        UBaseAttributeSet::GetManaAttribute(), bFound);
    float RequiredMana = 30.0f;
    
    // 检查法力值是否足够
    if (!bFound || CurrentMana < RequiredMana)
    {
        SendManaWarning(); // 显示法力不足提示
        return false;
    }
    
    return true;
}
复制代码

3. 装备和物品系统

装备属性要求检查

cpp 复制代码
bool UEquipmentComponent::CanEquipItem(const UItemData* ItemData) const
{
    if (!ItemData) return false;
    
    bool bFound;
    UAbilitySystemComponent* ASC = GetOwnerAbilitySystemComponent();
    
    // 检查力量要求
    float CurrentStrength = ASC->GetGameplayAttributeValue(
        UBaseAttributeSet::GetStrengthAttribute(), bFound);
    if (bFound && CurrentStrength < ItemData->RequiredStrength)
    {
        SendNotification("力量不足,无法装备此物品");
        return false;
    }
    
    // 检查等级要求
    float CurrentLevel = ASC->GetGameplayAttributeValue(
        UBaseAttributeSet::GetLevelAttribute(), bFound);
    if (bFound && CurrentLevel < ItemData->RequiredLevel)
    {
        SendNotification("等级不足,无法装备此物品");
        return false;
    }
    
    return true;
}
复制代码

4. AI 决策和行为树

AI 行为树中的条件判断

cpp 复制代码
// 在行为树装饰器或任务中
UBTDecorator_CheckHealth::CalculateRawConditionValue(...) const
{
    AAIController* AIController = ...;
    APawn* ControlledPawn = AIController->GetPawn();
    
    UAbilitySystemComponent* ASC = ControlledPawn->FindComponentByClass<UAbilitySystemComponent>();
    if (!ASC) return false;
    
    bool bFound;
    float CurrentHealth = ASC->GetGameplayAttributeValue(
        UBaseAttributeSet::GetHealthAttribute(), bFound);
    float MaxHealth = ASC->GetGameplayAttributeValue(
        UBaseAttributeSet::GetMaxHealthAttribute(), bFound);
    
    if (bFound)
    {
        float HealthPercent = CurrentHealth / MaxHealth;
        // 生命值低于30%时逃跑
        return HealthPercent < 0.3f;
    }
    
    return false;
}
复制代码

5. 成就和统计系统

成就条件检查

cpp 复制代码
void UAchievementManager::CheckDamageAchievements(float DamageDealt)
{
    bool bFound;
    UAbilitySystemComponent* ASC = PlayerController->GetAbilitySystemComponent();
    
    // 获取当前攻击力
    float AttackPower = ASC->GetGameplayAttributeValue(
        UBaseAttributeSet::GetAttackPowerAttribute(), bFound);
    
    // 单次攻击造成超过1000伤害的成就
    if (bFound && DamageDealt > 1000.0f)
    {
        UnlockAchievement("OneHitWonder");
    }
    
    // 累计伤害成就
    TotalDamageDealt += DamageDealt;
    if (TotalDamageDealt > 100000.0f)
    {
        UnlockAchievement("MasterDamageDealer");
    }
}
复制代码

6. 调试和开发工具

开发时属性监控

cpp 复制代码
// 调试命令显示所有属性
void UAttributeDebugComponent::DisplayAllAttributes()
{
    UAbilitySystemComponent* ASC = GetAbilitySystemComponent();
    if (!ASC) return;
    
    TArray<FGameplayAttribute> AllAttributes = GetRelevantAttributes();
    
    for (const FGameplayAttribute& Attribute : AllAttributes)
    {
        bool bFound;
        float Value = ASC->GetGameplayAttributeValue(Attribute, bFound);
        
        if (bFound)
        {
            FString AttributeName = Attribute.GetName();
            FString Message = FString::Printf(TEXT("%s: %.1f"), *AttributeName, Value);
            GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::White, Message);
        }
    }
}
复制代码

7. 实际项目中的最佳实践

封装工具函数

cpp 复制代码
// 工具类中封装常用操作
class GAMEMODULE_API UAttributeHelper
{
public:
    static float GetAttributeValue(AActor* Actor, FGameplayAttribute Attribute, float DefaultValue = 0.0f)
    {
        if (UAbilitySystemComponent* ASC = UAbilityFunctionLibrary::GetAbilitySystemComponent(Actor))
        {
            bool bFound;
            float Value = ASC->GetGameplayAttributeValue(Attribute, bFound);
            return bFound ? Value : DefaultValue;
        }
        return DefaultValue;
    }
    
    static bool HasEnoughResource(AActor* Actor, FGameplayAttribute ResourceAttribute, float RequiredAmount)
    {
        float CurrentResource = GetAttributeValue(Actor, ResourceAttribute);
        return CurrentResource >= RequiredAmount;
    }
};

// 使用封装函数
bool CanCastSpell = UAttributeHelper::HasEnoughResource(
    PlayerCharacter, 
    UBaseAttributeSet::GetManaAttribute(), 
    25.0f
);
复制代码

性能优化建议

cpp 复制代码
// 避免每帧调用,使用缓存或事件驱动
void UAttributeMonitorComponent::BeginPlay()
{
    Super::BeginPlay();
    
    // 监听属性变化而不是每帧查询
    if (UAbilitySystemComponent* ASC = GetAbilitySystemComponent())
    {
        ASC->GetGameplayAttributeValueChangeDelegate(UBaseAttributeSet::GetHealthAttribute())
            .AddUObject(this, &UAttributeMonitorComponent::OnHealthChanged);
    }
}

void UAttributeMonitorComponent::OnHealthChanged(const FOnAttributeChangeData& Data)
{
    // 只有属性实际变化时才更新
    UpdateHealthDisplay(Data.NewValue);
}

这些实际应用展示了 GetGameplayAttributeValue 在游戏各个系统中的重要作用,从基础的UI显示到复杂的游戏逻辑决策。

相关推荐
阿沁QWQ2 小时前
HTTP cookie 与 session
c++·浏览器·edge浏览器·cookie·session
知南x3 小时前
【STM32MP157 异核通信框架学习篇】(10)Linux下Remoteproc相关API (下)
linux·stm32·学习
铅笔小新z4 小时前
C++入门指南:开启你的编程之旅
开发语言·c++
星星20256 小时前
VSCode插件精选:4款高效UML绘图工具
笔记
_OP_CHEN10 小时前
Linux网络编程:(八)GCC/G++ 编译器完全指南:从编译原理到实战优化,手把手教你玩转 C/C++ 编译
linux·运维·c++·编译和链接·gcc/g++·编译优化·静态链接与动态链接
lkbhua莱克瓦2410 小时前
Java基础——方法
java·开发语言·笔记·github·学习方法
大锦终11 小时前
【动规】背包问题
c++·算法·动态规划
p666666666811 小时前
STM32-bootloader引导程序跳转机制笔记
笔记·stm32·嵌入式硬件
犯困的土子哥11 小时前
C++:哈希表
c++·哈希算法