中文注释:UrealEngine-5.2.1源码-AbilitySystemComponent.h
学习内容:
/**
* 返回属性集实例的引用(如果此组件中存在)
*
* @param AttributeSetClass 要查找的属性集类型
* @param bFound 如果属性集实例存在则设置为true
*/
UFUNCTION(BlueprintCallable, BlueprintPure = false, Category = "Gameplay Attributes")
const UAttributeSet* GetAttributeSet(TSubclassOf<UAttributeSet> AttributeSetClass) const;
这是一个典型的Unreal Engine游戏属性系统相关的函数声明。让我为您详细解释这个函数:
函数功能
此函数用于从游戏组件中查找并返回指定类型的属性集实例。
参数说明
-
AttributeSetClass: 要查找的属性集类型(使用TSubclassOf模板确保类型安全)
-
返回值: 找到的属性集实例的const指针,如果未找到则返回nullptr
使用示例
// 假设有这些属性集类
UCLASS()
class UHealthAttributeSet : public UAttributeSet { /*...*/ };
UCLASS()
class UManaAttributeSet : public UAttributeSet { /*...*/ };
// 使用示例
void ExampleUsage()
{
// 获取组件引用(假设在某个Actor中)
UActorComponent* Component = ...;
// 查找健康属性集
if (const UHealthAttributeSet* HealthSet = Component->GetAttributeSet(UHealthAttributeSet::StaticClass()))
{
// 成功找到健康属性集,可以使用它
float CurrentHealth = HealthSet->GetHealth();
}
// 或者检查是否存在某个属性集
const UAttributeSet* FoundSet = Component->GetAttributeSet(UManaAttributeSet::StaticClass());
if (FoundSet)
{
// 法力属性集存在
}
}
注意事项
-
BlueprintPure = false: 表示这个函数可能有副作用,不适合在蓝图中作为纯函数使用
-
const 返回值: 返回的是const指针,防止修改属性集
-
类型安全: 使用TSubclassOf确保传入的是有效的UAttributeSet子类
典型应用场景
-
在技能系统中访问角色的各种属性
-
在UI中显示角色属性值
-
在游戏逻辑中检查属性状态
-
实现属性修改和效果应用
这个函数是UE游戏能力系统(GAS)中的核心组件之一,用于管理角色的各种数值属性。
在实际项目中,GetAttributeSet 函数在游戏能力系统(GAS)中有着广泛的应用。以下是一些真实的使用场景:
1. 技能效果执行时获取属性
// 在GameplayEffectExecutionCalculation中
void UDamageExecution::Execute_Implementation(const FGameplayEffectCustomExecutionParameters& ExecutionParams, FGameplayEffectCustomExecutionOutput& OutExecutionOutput) const
{
// 获取目标角色的属性集
const UHealthAttributeSet* HealthSet = ExecutionParams.GetTargetAbilitySystemComponent()->GetAttributeSet<UHealthAttributeSet>();
const UCombatAttributeSet* CombatSet = ExecutionParams.GetTargetAbilitySystemComponent()->GetAttributeSet<UCombatAttributeSet>();
if (HealthSet && CombatSet)
{
// 计算伤害,考虑护甲等属性
float BaseDamage = 50.0f;
float ArmorReduction = CombatSet->GetArmor() * 0.1f;
float FinalDamage = FMath::Max(0, BaseDamage - ArmorReduction);
// 应用伤害到健康值
OutExecutionOutput.AddOutputModifier(FGameplayModifierEvaluatedData(
UHealthAttributeSet::GetHealthAttribute(),
EGameplayModOp::Additive,
-FinalDamage
));
}
}
2. UI 系统更新显示
// 在角色HUD Widget中
void UPlayerHUDWidget::NativeTick(const FGeometry& MyGeometry, float InDeltaTime)
{
Super::NativeTick(MyGeometry, InDeltaTime);
if (UAbilitySystemComponent* ASC = GetAbilitySystemComponent())
{
// 获取各种属性集来更新UI
if (const UHealthAttributeSet* HealthSet = ASC->GetAttributeSet<UHealthAttributeSet>())
{
HealthBar->SetPercent(HealthSet->GetHealth() / HealthSet->GetMaxHealth());
HealthText->SetText(FText::AsNumber(HealthSet->GetHealth()));
}
if (const UManaAttributeSet* ManaSet = ASC->GetAttributeSet<UManaAttributeSet>())
{
ManaBar->SetPercent(ManaSet->GetMana() / ManaSet->GetMaxMana());
}
if (const UStaminaAttributeSet* StaminaSet = ASC->GetAttributeSet<UStaminaAttributeSet>())
{
StaminaBar->SetPercent(StaminaSet->GetStamina() / StaminaSet->GetMaxStamina());
}
}
}
3. 条件检查和游戏逻辑
// 在自定义游戏能力中
bool UDashAbility::CanActivateAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayTagContainer* SourceTags, const FGameplayTagContainer* TargetTags, FGameplayTagContainer* OptionalRelevantTags) const
{
if (!Super::CanActivateAbility(Handle, ActorInfo, SourceTags, TargetTags, OptionalRelevantTags))
{
return false;
}
// 检查是否有足够的体力来施展冲刺
if (const UStaminaAttributeSet* StaminaSet = GetAbilitySystemComponentFromActorInfo()->GetAttributeSet<UStaminaAttributeSet>())
{
return StaminaSet->GetStamina() >= RequiredStaminaCost;
}
return false;
}
void UDashAbility::ActivateAbility(const FGameplayAbilitySpecHandle Handle, const FGameplayAbilityActorInfo* ActorInfo, const FGameplayAbilityActivationInfo ActivationInfo, const FGameplayEventData* TriggerEventData)
{
// 消耗体力
if (UStaminaAttributeSet* StaminaSet = GetAbilitySystemComponentFromActorInfo()->GetAttributeSet<UStaminaAttributeSet>())
{
// 应用体力消耗的GameplayEffect
FGameplayEffectSpecHandle SpecHandle = MakeOutgoingGameplayEffectSpec(StaminaCostEffect);
ApplyGameplayEffectSpecToOwner(Handle, ActorInfo, ActivationInfo, SpecHandle);
}
// 执行冲刺逻辑...
}
4. AI 行为树决策
// AI服务节点中检查属性状态
UBTService_CheckHealth::UBTService_CheckHealth()
{
NodeName = "Check Health Status";
}
void UBTService_CheckHealth::TickNode(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory, float DeltaSeconds)
{
Super::TickNode(OwnerComp, NodeMemory, DeltaSeconds);
AAIController* AIController = OwnerComp.GetAIOwner();
if (AIController && AIController->GetPawn())
{
if (UAbilitySystemComponent* ASC = AIController->GetPawn()->FindComponentByClass<UAbilitySystemComponent>())
{
if (const UHealthAttributeSet* HealthSet = ASC->GetAttributeSet<UHealthAttributeSet>())
{
float HealthPercent = HealthSet->GetHealth() / HealthSet->GetMaxHealth();
// 根据血量设置行为树变量
OwnerComp.GetBlackboardComponent()->SetValueAsBool(IsLowHealthKey.SelectedKeyName, HealthPercent < 0.3f);
OwnerComp.GetBlackboardComponent()->SetValueAsBool(IsCriticalHealthKey.SelectedKeyName, HealthPercent < 0.1f);
}
}
}
}
5. 物品和装备系统
// 装备物品时修改属性
void UEquippableItem::OnEquipped(AActor* Owner)
{
if (UAbilitySystemComponent* ASC = Owner->FindComponentByClass<UAbilitySystemComponent>())
{
// 检查角色是否有对应的属性集
if (const UCombatAttributeSet* CombatSet = ASC->GetAttributeSet<UCombatAttributeSet>())
{
// 应用装备加成
FGameplayEffectContextHandle EffectContext = ASC->MakeEffectContext();
EffectContext.AddSourceObject(this);
FGameplayEffectSpecHandle SpecHandle = ASC->MakeOutgoingSpec(EquipmentEffect, 1, EffectContext);
if (SpecHandle.IsValid())
{
ASC->ApplyGameplayEffectSpecToSelf(*SpecHandle.Data.Get());
}
}
}
}
6. 保存/加载系统
// 保存角色属性状态
void UPlayerSaveGame::SaveAttributes(UAbilitySystemComponent* ASC)
{
if (!ASC) return;
// 保存健康属性
if (const UHealthAttributeSet* HealthSet = ASC->GetAttributeSet<UHealthAttributeSet>())
{
SavedHealth = HealthSet->GetHealth();
SavedMaxHealth = HealthSet->GetMaxHealth();
}
// 保存法力属性
if (const UManaAttributeSet* ManaSet = ASC->GetAttributeSet<UManaAttributeSet>())
{
SavedMana = ManaSet->GetMana();
SavedMaxMana = ManaSet->GetMaxMana();
}
// 保存经验值
if (const UExperienceAttributeSet* ExpSet = ASC->GetAttributeSet<UExperienceAttributeSet>())
{
SavedExperience = ExpSet->GetExperience();
SavedLevel = ExpSet->GetLevel();
}
}
最佳实践建议
-
空指针检查:始终检查返回值是否为nullptr
-
缓存引用:对于频繁访问的属性集,考虑缓存引用
-
属性变化监听:使用属性变化委托而不是每帧查询
-
线程安全:确保在正确的时机访问属性集
这些实际应用展示了GetAttributeSet在游戏开发中的核心作用,是构建复杂属性系统的基石。
1745

被折叠的 条评论
为什么被折叠?



