ASC学习笔记0022:在不打算修改属性集时访问生成的属性集

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

学习内容:

/** 在不打算修改列表时访问生成的属性列表。 */
	const TArray<UAttributeSet*>& GetSpawnedAttributes() const;

这是一个C++代码片段,来自Unreal Engine项目。让我来解释这个函数声明:

函数说明

功能:获取已生成的属性集列表的只读引用

关键特点

  1. 返回类型const TArray<UAttributeSet*>&

    • 返回对 UAttributeSet 指针数组的常量引用

    • 避免拷贝整个数组,提高性能

    • 防止调用者修改原始数据

  2. const 成员函数

    • 函数末尾的 const 表示该函数不会修改类的成员变量

    • 可以在 const 对象上调用

  3. 使用场景

    • 只需要查看已生成的属性集,而不需要修改它们

    • 用于迭代、查询或显示属性信息

典型用法示例

// 假设在某个类的成员函数中
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;
}

关键优势

  1. 性能高效 - 返回引用避免数组拷贝

  2. 数据安全 - const引用防止意外修改

  3. 接口清晰 - 明确表示这是只读操作

  4. GAS集成 - 完美配合UE的Gameplay Ability System

这种设计模式在需要查看但不修改属性集的场景中非常实用,特别是在UI、存档、调试和AI系统中。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值