中文注释:UrealEngine-5.2.1源码-AbilitySystemComponent.h
学习内容:
cpp
/**
* 手动添加一个新的属性集,作为此能力系统组件的子对象。
* 此组件的所有子对象在初始化期间会自动添加。
*/
template <class T>
const T* AddAttributeSetSubobject(T* Subobject)
{
AddSpawnedAttribute(Subobject);
return Subobject;
}
这是一个用于游戏能力系统组件(Ability System Component)中动态添加属性集(Attribute Set)子对象的方法。让我为您详细解释这个函数:
函数分析
功能说明
-
目的:手动向能力系统组件添加一个属性集子对象
-
使用场景:当需要动态添加属性集,而不是在初始化期间自动添加时
-
返回值:返回添加的属性集指针(const限定)
关键组件
-
模板函数:支持任何继承自属性集基类的类型
-
AddSpawnedAttribute:内部方法,实际执行添加操作
-
返回const指针:防止外部意外修改
使用示例
cpp
// 假设有一个自定义属性集类
class UMyCustomAttributeSet : public UAttributeSet
{
// 属性定义...
};
// 在能力系统组件中使用
UMyCustomAttributeSet* NewAttributeSet = NewObject<UMyCustomAttributeSet>(this);
const UMyCustomAttributeSet* AddedSet = AddAttributeSetSubobject(NewAttributeSet);
设计考虑
-
灵活性:允许运行时动态添加属性集
-
类型安全:模板确保类型正确性
-
所有权明确:组件管理属性集的生命周期
-
接口一致性:与自动添加的属性集使用相同的基础设施
这种设计在需要条件性添加属性集或支持插件式架构时特别有用。
在实际项目中,AddAttributeSetSubobject 方法在Gameplay Ability System (GAS) 中有广泛的应用。以下是一些典型的使用场景和实际案例:
1. 角色能力组件初始化
基础角色类
cpp
// MyCharacter.h
UCLASS()
class AMyCharacter : public ACharacter, public IAbilitySystemInterface
{
GENERATED_BODY()
public:
AMyCharacter();
virtual UAbilitySystemComponent* GetAbilitySystemComponent() const override { return AbilitySystemComponent; }
protected:
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Abilities")
TObjectPtr<UMyAbilitySystemComponent> AbilitySystemComponent;
UPROPERTY()
TObjectPtr<UHealthAttributeSet> HealthAttributes;
UPROPERTY()
TObjectPtr<UManaAttributeSet> ManaAttributes;
UPROPERTY()
TObjectPtr<UCombatAttributeSet> CombatAttributes;
};
// MyCharacter.cpp
AMyCharacter::AMyCharacter()
{
// 创建能力系统组件
AbilitySystemComponent = CreateDefaultSubobject<UMyAbilitySystemComponent>("AbilitySystemComponent");
// 创建并添加属性集
HealthAttributes = CreateDefaultSubobject<UHealthAttributeSet>("HealthAttributes");
ManaAttributes = CreateDefaultSubobject<UManaAttributeSet>("ManaAttributes");
CombatAttributes = CreateDefaultSubobject<UCombatAttributeSet>("CombatAttributes");
// 设置组件依附关系
AbilitySystemComponent->SetupAttachment(RootComponent);
}
自定义能力系统组件
cpp
// MyAbilitySystemComponent.h
UCLASS()
class UMyAbilitySystemComponent : public UAbilitySystemComponent
{
GENERATED_BODY()
public:
template <class T>
const T* AddAttributeSetSubobject(T* Subobject)
{
AddSpawnedAttribute(Subobject);
return Subobject;
}
protected:
virtual void AddSpawnedAttribute(UAttributeSet* AttributeSet);
};
// MyAbilitySystemComponent.cpp
void UMyAbilitySystemComponent::AddSpawnedAttribute(UAttributeSet* AttributeSet)
{
if (AttributeSet)
{
SpawnedAttributes.Add(AttributeSet);
AddAttributeSetSubobject(AttributeSet);
// 触发属性集初始化事件
OnAttributeSetAdded.Broadcast(AttributeSet);
}
}
2. 复杂的职业系统
不同职业的属性配置
cpp
// WarriorCharacter.cpp
AWarriorCharacter::AWarriorCharacter()
{
AbilitySystemComponent = CreateDefaultSubobject<UMyAbilitySystemComponent>("AbilitySystemComponent");
// 战士特有属性集
HealthAttributes = AbilitySystemComponent->AddAttributeSetSubobject(CreateDefaultSubobject<UHealthAttributeSet>("HealthAttributes"));
StaminaAttributes = AbilitySystemComponent->AddAttributeSetSubobject(CreateDefaultSubobject<UStaminaAttributeSet>("StaminaAttributes"));
StrengthAttributes = AbilitySystemComponent->AddAttributeSetSubobject(CreateDefaultSubobject<UStrengthAttributeSet>("StrengthAttributes"));
DefenseAttributes = AbilitySystemComponent->AddAttributeSetSubobject(CreateDefaultSubobject<UDefenseAttributeSet>("DefenseAttributes"));
}
// MageCharacter.cpp
AMageCharacter::AMageCharacter()
{
AbilitySystemComponent = CreateDefaultSubobject<UMyAbilitySystemComponent>("AbilitySystemComponent");
// 法师特有属性集
HealthAttributes = AbilitySystemComponent->AddAttributeSetSubobject(CreateDefaultSubobject<UHealthAttributeSet>("HealthAttributes"));
ManaAttributes = AbilitySystemComponent->AddAttributeSetSubobject(CreateDefaultSubobject<UManaAttributeSet>("ManaAttributes"));
IntelligenceAttributes = AbilitySystemComponent->AddAttributeSetSubobject(CreateDefaultSubobject<UIntelligenceAttributeSet>("IntelligenceAttributes"));
SpellPowerAttributes = AbilitySystemComponent->AddAttributeSetSubobject(CreateDefaultSubobject<USpellPowerAttributeSet>("SpellPowerAttributes"));
}
3. 动态属性集管理
运行时添加/移除属性集
cpp
// 动态添加临时属性集(如增益效果)
void UMyAbilitySystemComponent::AddTemporaryAttributeSet(UAttributeSet* TempAttributeSet)
{
if (TempAttributeSet && !TemporaryAttributeSets.Contains(TempAttributeSet))
{
AddAttributeSetSubobject(TempAttributeSet);
TemporaryAttributeSets.Add(TempAttributeSet);
// 通知属性变化
ForceReplication();
}
}
void UMyAbilitySystemComponent::RemoveTemporaryAttributeSet(UAttributeSet* TempAttributeSet)
{
if (TemporaryAttributeSets.Remove(TempAttributeSet))
{
RemoveSpawnedAttribute(TempAttributeSet);
}
}
4. 装备系统集成
装备提供的属性集
cpp
// EquipmentComponent.cpp
void UEquipmentComponent::OnEquipmentEquipped(UEquipmentItem* Equipment)
{
if (Equipment && Equipment->GrantedAttributeSet)
{
// 为装备创建属性集实例
UAttributeSet* EquipmentAttributeSet = NewObject<UAttributeSet>(GetOwner(), Equipment->GrantedAttributeSet);
// 添加到能力系统组件
if (UAbilitySystemComponent* ASC = GetOwnerAbilitySystemComponent())
{
if (UMyAbilitySystemComponent* MyASC = Cast<UMyAbilitySystemComponent>(ASC))
{
MyASC->AddAttributeSetSubobject(EquipmentAttributeSet);
EquippedAttributeSets.Add(EquipmentAttributeSet);
}
}
}
}
5. 状态效果系统
状态效果属性集
cpp
// StatusEffectComponent.cpp
void UStatusEffectComponent::ApplyStatusEffect(FStatusEffectHandle EffectHandle)
{
if (UStatusEffect* StatusEffect = EffectHandle.GetEffect())
{
// 创建状态效果属性集
UStatusEffectAttributeSet* EffectAttributeSet = NewObject<UStatusEffectAttributeSet>(this);
EffectAttributeSet->InitializeFromEffect(StatusEffect);
// 添加到能力系统
if (UMyAbilitySystemComponent* MyASC = GetMyAbilitySystemComponent())
{
MyASC->AddAttributeSetSubobject(EffectAttributeSet);
ActiveEffectAttributeSets.Add(EffectHandle, EffectAttributeSet);
}
}
}
6. 网络同步优化
属性复制配置
cpp
// 在属性集中配置网络同步
UCLASS()
class UHealthAttributeSet : public UAttributeSet
{
GENERATED_BODY()
public:
UPROPERTY(BlueprintReadOnly, Category = "Health", ReplicatedUsing = OnRep_Health)
FGameplayAttributeData Health;
UPROPERTY(BlueprintReadOnly, Category = "Health", ReplicatedUsing = OnRep_MaxHealth)
FGameplayAttributeData MaxHealth;
// 复制通知
UFUNCTION()
void OnRep_Health(const FGameplayAttributeData& OldHealth);
UFUNCTION()
void OnRep_MaxHealth(const FGameplayAttributeData& OldMaxHealth);
// 网络复制
virtual void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override;
};
实际项目中的最佳实践
-
明确的命名约定:属性集名称要清晰表达其用途
-
模块化设计:每个属性集专注于单一职责
-
内存管理:及时清理不再使用的属性集
-
网络优化:合理配置复制属性,减少带宽占用
-
错误处理:添加适当的空指针检查和验证
这种模式在大型项目中特别有用,因为它提供了清晰的架构来管理复杂的游戏属性系统,同时保持了代码的可维护性和扩展性。