ASC学习笔记0019:返回给定游戏属性的当前值,如果未找到该属性则返回零。
中文注释:UrealEngine-5.2.1源码-AbilitySystemComponent.h
学习内容:
/*** 返回给定游戏属性的当前值,如果未找到该属性则返回零。* 注意:这不会考虑预测的游戏效果修饰符,因此客户端的值可能并不总是准确的。** @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:输出参数,表示属性是否存在
使用示例
// 在C++中使用
bool bAttributeFound;
float CurrentHealth = AttributeComponent->GetGameplayAttributeValue( UBaseAttributeSet::GetHealthAttribute(), bAttributeFound
);if (bAttributeFound)
{// 处理健康值UE_LOG(LogTemp, Warning, TEXT("Current Health: %f"), CurrentHealth);
}
blueprint
// 在蓝图中使用
[Get Gameplay Attribute Value]Attribute: [Get Health Attribute] bFound: (输出引脚,连接到Branch节点)Return Value: 连接到其他节点
重要注意事项
-
客户端准确性:如注释所述,这不考虑预测的效果修饰符,客户端值可能与服务器不同步
-
属性查找:
bFound参数很重要,可以区分"属性值为0"和"属性不存在"的情况 -
性能考虑:频繁调用可能影响性能,建议缓存结果
典型应用场景
-
UI显示角色属性
-
技能条件检查
-
游戏逻辑决策
-
调试和信息显示
这个函数是Gameplay Ability System (GAS) 中访问属性值的常用方法之一。
在实际项目中,GetGameplayAttributeValue 函数有广泛的应用场景。以下是一些具体的实际用例:
1. UI 显示和更新
HUD 组件中显示角色属性
// 在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. 技能条件和消耗检查
技能释放前的条件验证
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. 装备和物品系统
装备属性要求检查
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 行为树中的条件判断
// 在行为树装饰器或任务中
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. 成就和统计系统
成就条件检查
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. 调试和开发工具
开发时属性监控
// 调试命令显示所有属性
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. 实际项目中的最佳实践
封装工具函数
// 工具类中封装常用操作
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
);
性能优化建议
// 避免每帧调用,使用缓存或事件驱动
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显示到复杂的游戏逻辑决策。
