ASC学习笔记0022:在不打算修改属性集时访问生成的属性集
中文注释:UrealEngine-5.2.1源码-AbilitySystemComponent.h
学习内容:
/** 在不打算修改列表时访问生成的属性列表。 */const TArray<UAttributeSet*>& GetSpawnedAttributes() const;
这是一个C++代码片段,来自Unreal Engine项目。让我来解释这个函数声明:
函数说明
功能:获取已生成的属性集列表的只读引用
关键特点:
-
返回类型:
const TArray<UAttributeSet*>&-
返回对
UAttributeSet指针数组的常量引用 -
避免拷贝整个数组,提高性能
-
防止调用者修改原始数据
-
-
const 成员函数:
-
函数末尾的
const表示该函数不会修改类的成员变量 -
可以在 const 对象上调用
-
-
使用场景:
-
只需要查看已生成的属性集,而不需要修改它们
-
用于迭代、查询或显示属性信息
-
典型用法示例
// 假设在某个类的成员函数中
void SomeFunction() const
{// 获取属性列表(只读访问)const TArray<UAttributeSet*>& Attributes = GetSpawnedAttributes();// 可以遍历查看,但不能修改for (UAttributeSet* Attr : Attributes){if (Attr){// 查看属性信息...UE_LOG(LogTemp, Warning, TEXT("Attribute Set: %s"), *Attr->GetName());}}// 以下代码会编译错误(因为是const引用):// Attributes.Add(NewAttribute); // 错误!// Attributes.RemoveAt(0); // 错误!
}
这种设计模式在UE中很常见,既保证了数据的安全性,又提供了高效的访问方式。
在UE项目中,这个函数在Gameplay Ability System (GAS) 架构中有广泛的应用。以下是几个实际应用场景:
1. UI显示属性值
// 在HUD或Widget中显示角色所有属性
void UAttributeWidget::UpdateAttributeDisplay()
{if (ACharacter* PlayerCharacter = GetPlayerCharacter()){if (UAbilitySystemComponent* ASC = PlayerCharacter->FindComponentByClass<UAbilitySystemComponent>()){const TArray<UAttributeSet*>& AttributeSets = ASC->GetSpawnedAttributes();for (UAttributeSet* AttributeSet : AttributeSets){if (UMyHealthAttributeSet* HealthAttrs = Cast<UMyHealthAttributeSet>(AttributeSet)){HealthBar->SetPercent(HealthAttrs->GetHealth() / HealthAttrs->GetMaxHealth());}else if (UMyStaminaAttributeSet* StaminaAttrs = Cast<UMyStaminaAttributeSet>(AttributeSet)){StaminaBar->SetPercent(StaminaAttrs->GetStamina() / StaminaAttrs->GetMaxStamina());}}}}
}
2. 属性监听和响应
// 监听所有属性变化
void UAttributeMonitorComponent::InitializeAttributeListeners()
{if (UAbilitySystemComponent* ASC = GetAbilitySystemComponent()){const TArray<UAttributeSet*>& AttributeSets = ASC->GetSpawnedAttributes();for (UAttributeSet* AttributeSet : AttributeSets){if (UMyHealthAttributeSet* HealthAttrs = Cast<UMyHealthAttributeSet>(AttributeSet)){// 监听血量变化ASC->GetGameplayAttributeValueChangeDelegate(UMyHealthAttributeSet::GetHealthAttribute()).AddUObject(this, &UAttributeMonitorComponent::OnHealthChanged);}}}
}
3. 存档系统
// 保存所有属性状态
void UGameSaveSystem::SaveAttributes(UGameSave* SaveGame, UAbilitySystemComponent* ASC)
{if (!SaveGame || !ASC) return;const TArray<UAttributeSet*>& AttributeSets = ASC->GetSpawnedAttributes();for (UAttributeSet* AttributeSet : AttributeSets){if (UMyHealthAttributeSet* HealthAttrs = Cast<UMyHealthAttributeSet>(AttributeSet)){SaveGame->SavedHealth = HealthAttrs->GetHealth();SaveGame->SavedMaxHealth = HealthAttrs->GetMaxHealth();}else if (UMyManaAttributeSet* ManaAttrs = Cast<UMyManaAttributeSet>(AttributeSet)){SaveGame->SavedMana = ManaAttrs->GetMana();SaveGame->SavedMaxMana = ManaAttrs->GetMaxMana();}}
}
4. Debug和开发工具
// 在控制台显示所有属性值
void AMyPlayerController::DebugShowAttributes()
{if (UAbilitySystemComponent* ASC = GetAbilitySystemComponent()){const TArray<UAttributeSet*>& AttributeSets = ASC->GetSpawnedAttributes();UE_LOG(LogTemp, Warning, TEXT("=== Current Attributes ==="));for (UAttributeSet* AttributeSet : AttributeSets){FString AttributeSetName = AttributeSet->GetClass()->GetName();UE_LOG(LogTemp, Warning, TEXT("Attribute Set: %s"), *AttributeSetName);// 使用反射获取所有属性值for (TFieldIterator<FProperty> PropIt(AttributeSet->GetClass()); PropIt; ++PropIt){FProperty* Property = *PropIt;if (Property->IsA<FGameplayAttribute>()){// 显示属性名称和值...}}}}
}
5. 条件检查和验证
// 检查是否满足技能施放条件
bool UMyGameplayAbility::CheckAttributeRequirements()
{if (UAbilitySystemComponent* ASC = GetAbilitySystemComponentFromActorInfo()){const TArray<UAttributeSet*>& AttributeSets = ASC->GetSpawnedAttributes();for (UAttributeSet* AttributeSet : AttributeSets){if (UMyResourceAttributeSet* ResourceAttrs = Cast<UMyResourceAttributeSet>(AttributeSet)){// 检查法力值是否足够if (ResourceAttrs->GetMana() < RequiredManaCost){return false;}// 检查血量是否高于最低要求if (ResourceAttrs->GetHealth() < MinimumHealthThreshold){return false;}}}}return true;
}
6. AI决策系统
// AI根据属性状态做出决策
ECombatBehavior UMyAIController::EvaluateCombatBehavior()
{if (UAbilitySystemComponent* ASC = GetPawn()->FindComponentByClass<UAbilitySystemComponent>()){const TArray<UAttributeSet*>& AttributeSets = ASC->GetSpawnedAttributes();for (UAttributeSet* AttributeSet : AttributeSets){if (UMyHealthAttributeSet* HealthAttrs = Cast<UMyHealthAttributeSet>(AttributeSet)){float HealthPercent = HealthAttrs->GetHealth() / HealthAttrs->GetMaxHealth();if (HealthPercent < 0.3f) return ECombatBehavior::Retreat;if (HealthPercent < 0.6f) return ECombatBehavior::Defensive;}}}return ECombatBehavior::Aggressive;
}
关键优势
-
性能高效 - 返回引用避免数组拷贝
-
数据安全 - const引用防止意外修改
-
接口清晰 - 明确表示这是只读操作
-
GAS集成 - 完美配合UE的Gameplay Ability System
这种设计模式在需要查看但不修改属性集的场景中非常实用,特别是在UI、存档、调试和AI系统中。
