ASC学习笔记0021:移除所有当前属性集并注册传入数组中的属性集
中文注释:UrealEngine-5.2.1源码-AbilitySystemComponent.h
学习内容:
/** 移除所有当前属性集并注册传入数组中的属性集。注意,在可能的情况下,最好直接调用Add/Remove。 */void SetSpawnedAttributes(const TArray<UAttributeSet*>& NewAttributeSet);UE_DEPRECATED(5.1, "此函数将变为私有。请改用 Add/Remove SpawnedAttributes")TArray<UAttributeSet*>& GetSpawnedAttributes_Mutable();
这段代码是一个属性集管理函数的声明,包含一个设置函数和一个已弃用的获取函数。让我为您详细解释:
函数说明
SetSpawnedAttributes
void SetSpawnedAttributes(const TArray<UAttributeSet*>& NewAttributeSet);
功能:
-
移除所有当前已存在的属性集
-
注册传入数组中的新属性集
-
用于批量替换属性集
参数:
-
NewAttributeSet:包含新属性集的数组引用
使用建议:
-
在可能的情况下,优先使用
Add/Remove单个属性集的方法 -
此方法适用于需要完全替换属性集的情况
GetSpawnedAttributes_Mutable (已弃用)
UE_DEPRECATED(5.1, "此函数将变为私有。请改用 Add/Remove SpawnedAttributes")
TArray<UAttributeSet*>& GetSpawnedAttributes_Mutable();
弃用信息:
-
从 UE5.1 开始弃用
-
未来版本将变为私有函数
-
建议使用 Add/Remove 方法来操作属性集
迁移建议
不再推荐的做法:
// 不推荐 - 直接修改返回的数组
TArray<UAttributeSet*>& Attrs = GetSpawnedAttributes_Mutable();
Attrs.Add(NewAttributeSet);
推荐的做法:
// 推荐 - 使用专门的添加方法
AddSpawnedAttribute(NewAttributeSet);// 或者移除方法
RemoveSpawnedAttribute(OldAttributeSet);
设计意图
这样的设计变更体现了更好的封装性,避免了直接暴露内部数据结构的风险,提供了更安全、可控的属性集管理接口。
在实际项目中,这些函数主要用于管理角色的属性系统。让我通过具体场景来说明:
1. 属性集的基本使用
角色初始化时设置属性集
// 在角色或玩家状态的初始化中
void AMyPlayerState::InitializeAttributes()
{TArray<UAttributeSet*> NewAttributeSets;// 创建基础属性集UHealthAttributeSet* HealthAttr = CreateDefaultSubobject<UHealthAttributeSet>(TEXT("HealthAttr"));UManaAttributeSet* ManaAttr = CreateDefaultSubobject<UManaAttributeSet>(TEXT("ManaAttr"));UStaminaAttributeSet* StaminaAttr = CreateDefaultSubobject<UStaminaAttributeSet>(TEXT("StaminaAttr"));NewAttributeSets.Add(HealthAttr);NewAttributeSets.Add(ManaAttr);NewAttributeSets.Add(StaminaAttr);// 批量设置属性集SetSpawnedAttributes(NewAttributeSets);
}
2. 动态添加/移除属性集
装备系统
// 装备物品时添加特殊属性
void UEquipmentComponent::EquipItem(UItem* Item)
{if (Item->AttributeSet){// 添加物品带来的属性集AddSpawnedAttribute(Item->AttributeSet);// 触发属性更新OnAttributesChanged.Broadcast();}
}// 卸载物品时移除属性
void UEquipmentComponent::UnequipItem(UItem* Item)
{if (Item->AttributeSet){RemoveSpawnedAttribute(Item->AttributeSet);OnAttributesChanged.Broadcast();}
}
状态效果系统
// 施加增益/减益效果
void UStatusEffectComponent::ApplyEffect(UStatusEffect* Effect)
{if (Effect->AttributeSet){AddSpawnedAttribute(Effect->AttributeSet);// 启动效果计时器FTimerHandle TimerHandle;GetWorld()->GetTimerManager().SetTimer(TimerHandle, [this, Effect]() { RemoveSpawnedAttribute(Effect->AttributeSet); },Effect->Duration, false);}
}
3. 职业系统中的应用
切换职业
void ACharacterClassSystem::SwitchClass(UCharacterClass* NewClass)
{// 获取当前玩家状态AMyPlayerState* PS = GetPlayerState<AMyPlayerState>();if (!PS) return;// 移除旧职业的属性集for (UAttributeSet* OldAttrSet : OldClass->ClassAttributeSets){PS->RemoveSpawnedAttribute(OldAttrSet);}// 添加新职业的属性集for (UAttributeSet* NewAttrSet : NewClass->ClassAttributeSets){PS->AddSpawnedAttribute(NewAttrSet);}
}
4. 多人游戏中的注意事项
// 确保在服务端执行属性操作
void AMyCharacter::Server_AddBuff_Implementation(UBuff* Buff)
{if (GetLocalRole() == ROLE_Authority && Buff->AttributeSet){AddSpawnedAttribute(Buff->AttributeSet);// 同步到客户端Client_OnBuffAdded(Buff);}
}// 客户端响应
void AMyCharacter::Client_OnBuffAdded_Implementation(UBuff* Buff)
{// 客户端更新UI等OnBuffAdded.Broadcast(Buff);
}
5. 实际项目中的最佳实践
封装属性管理
// 专门的属性管理器
UCLASS()
class UAttributeManager : public UObject
{
public:void InitializeDefaultAttributes();void AddTemporaryAttribute(UAttributeSet* AttributeSet, float Duration);void RemoveAttributeByType(TSubclassOf<UAttributeSet> AttributeSetClass);private:TArray<UAttributeSet*> TemporaryAttributes;AAbilitySystemComponent* ASC;
};
属性集工厂模式
// 根据需要创建属性集
UAttributeSet* UAttributeFactory::CreateAttributeSet(EAttributeType Type)
{switch (Type){case EAttributeType::Health:return NewObject<UHealthAttributeSet>();case EAttributeType::Mana:return NewObject<UManaAttributeSet>();case EAttributeType::Stamina:return NewObject<UStaminaAttributeSet>();default:return nullptr;}
}
6. 调试和验证
// 验证属性集操作
void ValidateAttributeOperations()
{// 检查重复添加if (HasAttributeSetOfType<UHealthAttributeSet>()){UE_LOG(LogTemp, Warning, TEXT("Health attribute set already exists"));return;}// 安全添加if (UHealthAttributeSet* HealthSet = CreateHealthAttributeSet()){AddSpawnedAttribute(HealthSet);}
}
这些实际应用展示了如何在游戏系统中灵活管理属性集,特别是在需要动态修改角色属性的场景中。关键是要遵循引擎的推荐做法,使用 Add/Remove 而不是直接操作内部数组。
