中文注释:UrealEngine-5.2.1源码-AbilitySystemComponent.h
学习内容:
/** 移除一个现有的属性集 */
void RemoveSpawnedAttribute(UAttributeSet* Attribute);
这是一个在Gameplay Ability System (GAS) 中常见的函数声明,用于从Ability System Component中移除已添加的属性集。以下是这个函数的典型实现方式:
基本实现
void UYourComponent::RemoveSpawnedAttribute(UAttributeSet* Attribute)
{
if (!Attribute || !GetOwnerActor())
{
return;
}
// 从已生成的属性集列表中移除
SpawnedAttributes.Remove(Attribute);
// 如果这个属性集还在主属性集列表中,也从中移除
if (UAbilitySystemComponent* ASC = GetAbilitySystemComponent())
{
ASC->RemoveSpawnedAttribute(Attribute);
}
// 可选:销毁属性集对象
if (Attribute->IsValidLowLevel())
{
Attribute->ConditionalBeginDestroy();
}
}
更完整的实现示例
void UYourAbilitySystemComponent::RemoveSpawnedAttribute(UAttributeSet* Attribute)
{
if (!Attribute)
{
UE_LOG(LogTemp, Warning, TEXT("Attempted to remove null AttributeSet"));
return;
}
if (!SpawnedAttributes.Contains(Attribute))
{
UE_LOG(LogTemp, Warning, TEXT("AttributeSet not found in SpawnedAttributes"));
return;
}
// 从内部列表中移除
SpawnedAttributes.Remove(Attribute);
// 从ASC的属性集列表中移除
FGameplayAttributeData* AttributeData = nullptr;
for (auto It = AttributeSetMap.CreateIterator(); It; ++It)
{
if (It.Value() == Attribute)
{
It.RemoveCurrent();
break;
}
}
// 清理并销毁
Attribute->PreDestroy();
Attribute->ConditionalBeginDestroy();
UE_LOG(LogTemp, Log, TEXT("Successfully removed AttributeSet: %s"),
*GetNameSafe(Attribute->GetClass()));
}
使用示例
// 假设你有一个对属性集的引用
UAttributeSet* HealthAttributeSet = FindObject<UAttributeSet>(...);
// 移除属性集
RemoveSpawnedAttribute(HealthAttributeSet);
HealthAttributeSet = nullptr; // 避免悬空指针
注意事项
-
空指针检查:始终验证输入参数
-
所有权管理:确保正确管理属性集的生命周期
-
组件验证:确认Ability System Component有效
-
列表一致性:保持所有相关列表的同步更新
-
内存管理:适当销毁不再使用的对象
在GAS中的典型使用场景
-
动态添加/移除角色的属性集
-
处理装备系统的属性加成
-
实现临时的状态效果
-
清理不再需要的属性数据
这个函数通常在需要动态管理角色属性时使用,特别是在运行时需要修改属性集配置的情况下。
在实际项目中,RemoveSpawnedAttribute 函数在GAS系统中有着广泛的应用场景。以下是一些具体的实际应用案例:
1. 装备系统 - 动态属性管理
// 装备组件中管理装备带来的属性集
void UEquipmentComponent::UnequipItem(UEquipableItem* Item)
{
if (!Item || !Item->GetAttributeSet())
{
return;
}
// 移除装备提供的属性集
if (UAbilitySystemComponent* ASC = GetAbilitySystemComponent())
{
ASC->RemoveSpawnedAttribute(Item->GetAttributeSet());
}
// 从本地记录中移除
EquippedAttributeSets.Remove(Item->GetAttributeSet());
// 广播装备移除事件
OnItemUnequipped.Broadcast(Item);
}
// 装备物品时的对应函数
void UEquipmentComponent::EquipItem(UEquipableItem* Item)
{
if (UAbilitySystemComponent* ASC = GetAbilitySystemComponent())
{
UAttributeSet* NewAttributeSet = NewObject<UAttributeSet>(this, Item->AttributeSetClass);
ASC->AddSpawnedAttribute(NewAttributeSet);
EquippedAttributeSets.Add(NewAttributeSet);
}
}
2. 状态效果系统 - 临时属性加成
// 状态效果组件管理临时属性
void UStatusEffectComponent::RemoveStatusEffect(FGameplayTag EffectTag)
{
if (FStatusEffectData* EffectData = ActiveEffects.Find(EffectTag))
{
if (EffectData->AttributeSet && EffectData->AttributeSet->IsValidLowLevel())
{
// 移除状态效果对应的属性集
if (UAbilitySystemComponent* ASC = GetAbilitySystemComponent())
{
ASC->RemoveSpawnedAttribute(EffectData->AttributeSet);
}
}
ActiveEffects.Remove(EffectTag);
OnStatusEffectRemoved.Broadcast(EffectTag);
}
}
// 添加临时状态效果
void UStatusEffectComponent::ApplyStatusEffect(TSubclassOf<UAttributeSet> EffectAttributeClass, float Duration)
{
if (UAbilitySystemComponent* ASC = GetAbilitySystemComponent())
{
UAttributeSet* NewEffectAttribute = NewObject<UAttributeSet>(this, EffectAttributeClass);
ASC->AddSpawnedAttribute(NewEffectAttribute);
FStatusEffectData NewEffect;
NewEffect.AttributeSet = NewEffectAttribute;
NewEffect.RemainingTime = Duration;
ActiveEffects.Add(EffectAttributeClass->GetFName(), NewEffect);
}
}
3. 职业/专精系统
// 角色职业管理
void UCharacterClassComponent::SwitchClass(UCharacterClass* NewClass)
{
if (CurrentClassAttributeSet)
{
// 移除旧职业的属性集
if (UAbilitySystemComponent* ASC = GetAbilitySystemComponent())
{
ASC->RemoveSpawnedAttribute(CurrentClassAttributeSet);
CurrentClassAttributeSet = nullptr;
}
}
// 添加新职业的属性集
if (NewClass && NewClass->ClassAttributeSet)
{
UAttributeSet* NewAttributeSet = NewObject<UAttributeSet>(this, NewClass->ClassAttributeSet);
if (UAbilitySystemComponent* ASC = GetAbilitySystemComponent())
{
ASC->AddSpawnedAttribute(NewAttributeSet);
CurrentClassAttributeSet = NewAttributeSet;
}
}
CurrentClass = NewClass;
OnClassChanged.Broadcast(NewClass);
}
4. 技能树/天赋系统
// 天赋系统管理选择的属性加成
void UTalentSystemComponent::ResetTalents()
{
if (UAbilitySystemComponent* ASC = GetAbilitySystemComponent())
{
// 移除所有通过天赋添加的属性集
for (UAttributeSet* TalentAttribute : ActiveTalentAttributes)
{
if (TalentAttribute && TalentAttribute->IsValidLowLevel())
{
ASC->RemoveSpawnedAttribute(TalentAttribute);
}
}
}
ActiveTalentAttributes.Empty();
SelectedTalents.Empty();
// 重新应用基础职业属性
ApplyBaseClassAttributes();
}
5. 多人游戏中的同步处理
// 在网络游戏中安全地处理属性集移除
void UPlayerCharacter::Server_RemoveAttributeSet_Implementation(UAttributeSet* AttributeSet)
{
if (GetLocalRole() == ROLE_Authority && AttributeSet)
{
// 服务器端移除
if (UAbilitySystemComponent* ASC = GetAbilitySystemComponent())
{
ASC->RemoveSpawnedAttribute(AttributeSet);
}
// 通知客户端
Multicast_OnAttributeSetRemoved(AttributeSet);
}
}
// 客户端响应
void UPlayerCharacter::Multicast_OnAttributeSetRemoved_Implementation(UAttributeSet* AttributeSet)
{
// 客户端清理本地引用
if (GetLocalRole() != ROLE_Authority && AttributeSet)
{
// 避免客户端重复销毁
if (OwnedAttributeSets.Contains(AttributeSet))
{
OwnedAttributeSets.Remove(AttributeSet);
}
}
}
6. 完整的生命周期管理
// 在角色销毁时清理所有动态属性集
void AAdvancedCharacter::BeginDestroy()
{
// 清理所有动态添加的属性集
for (UAttributeSet* DynamicAttributeSet : DynamicAttributeSets)
{
if (DynamicAttributeSet && DynamicAttributeSet->IsValidLowLevel())
{
if (UAbilitySystemComponent* ASC = GetAbilitySystemComponent())
{
ASC->RemoveSpawnedAttribute(DynamicAttributeSet);
}
}
}
DynamicAttributeSets.Empty();
Super::BeginDestroy();
}
// 安全的属性集移除函数
void AAdvancedCharacter::SafeRemoveAttributeSet(UAttributeSet* AttributeSet)
{
if (!AttributeSet || !IsValid(AttributeSet))
{
return;
}
// 检查是否属于这个角色
if (!DynamicAttributeSets.Contains(AttributeSet))
{
UE_LOG(LogGame, Warning, TEXT("Attempting to remove AttributeSet that doesn't belong to this character"));
return;
}
// 从ASC移除
if (UAbilitySystemComponent* ASC = GetAbilitySystemComponent())
{
ASC->RemoveSpawnedAttribute(AttributeSet);
}
// 从本地记录移除
DynamicAttributeSets.Remove(AttributeSet);
// 标记为待销毁
AttributeSet->MarkAsGarbage();
}
实际项目中的最佳实践
-
引用管理:始终保持对动态属性集的引用,避免内存泄漏
-
网络同步:在多人游戏中确保服务器和客户端状态一致
-
错误处理:添加充分的空指针和有效性检查
-
生命周期:在适当的时机(如角色销毁、关卡切换)清理属性集
-
性能考虑:避免频繁的添加/移除操作,使用属性修饰器(Modifiers)代替
这些实际应用展示了RemoveSpawnedAttribute在构建复杂游戏系统时的重要性,特别是在需要动态修改角色属性的RPG、MMO等游戏类型中。
355

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



