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显示到复杂的游戏逻辑决策。

相关推荐
一只乔哇噻1 天前
java后端工程师+AI大模型开发进修ing(研一版‖day60)
java·开发语言·人工智能·学习·语言模型
Dolphin_Home1 天前
笔记:SpringBoot静态类调用Bean的2种方案(小白友好版)
java·spring boot·笔记
暗然而日章1 天前
C++基础:Stanford CS106L学习笔记 4 容器(关联式容器)
c++·笔记·学习
盐焗西兰花1 天前
鸿蒙学习实战之路:Tabs 组件开发场景最佳实践
学习·华为·harmonyos
巨人张1 天前
C++火柴人跑酷
开发语言·c++
_Kayo_1 天前
Next.js 路由 简单学习笔记
笔记·学习·next.js
盐焗西兰花1 天前
鸿蒙学习实战之路 - 瀑布流操作实现
学习·华为·harmonyos
酒尘&1 天前
Hook学习-上篇
前端·学习·react.js·前端框架·react
qq_381454991 天前
Python学习技巧
开发语言·python·学习
im_AMBER1 天前
算法笔记 18 二分查找
数据结构·笔记·学习·算法