> 技术文档 > 虚幻引擎5 GAS开发俯视角RPG游戏 #06-10:预分配更改

虚幻引擎5 GAS开发俯视角RPG游戏 #06-10:预分配更改

目标: 将属性控制在0-Max之间

1.重写PreAttributeChange()函数, 这个函数会在AttributeSet里的监听的值发生改变前触发回调

Source/CC_Aura/Public/AbilitySystem/CC_AttributeSet.h:

virtual void PreAttributeChange(const FGameplayAttribute& Attribute, float& NewValue) override;

Source/CC_Aura/Private/AbilitySystem/CC_AttributeSet.cpp:

void UCC_AttributeSet::PreAttributeChange(const FGameplayAttribute& Attribute, float& NewValue){Super::PreAttributeChange(Attribute, NewValue);if (Attribute == GetHealthAttribute()){UE_LOG(LogTemp, Warning, TEXT(\"Health : %f.\"), NewValue);}if (Attribute == GetMaxHealthAttribute()){UE_LOG(LogTemp, Warning, TEXT(\"MaxHealth : %f.\"), NewValue);}if (Attribute == GetManaAttribute()){UE_LOG(LogTemp, Warning, TEXT(\"Mana : %f.\"), NewValue);}if (Attribute == GetMaxManaAttribute()){UE_LOG(LogTemp, Warning, TEXT(\"MaxMana : %f.\"), NewValue);}}

这是一个关于虚幻引擎(Unreal Engine)中Gameplay Ability System(GAS)的问题。PreAttributeChange是一个虚函数,用于在游戏属性(Attribute)值改变前进行预处理。

这个函数的作用是:

  1. 在属性值实际改变前被调用
  2. 可以在这里对NewValue进行修改或验证
  3. 常用于实现属性值的限制(如生命值不能超过最大值)
  4. 也可以在这里触发其他逻辑(如属性变化时的特效)

典型用法示例:

virtual void PreAttributeChange(const FGameplayAttribute& Attribute, float& NewValue) override{ // 如果是生命值属性 if (Attribute == GetHealthAttribute()) { // 确保生命值不会超过最大值 NewValue = FMath::Clamp(NewValue, 0.0f, GetMaxHealth()); } // 其他属性处理...}

这个函数是GAS系统中属性变化处理流程的一部分,通常与PostGameplayEffectExecute等函数配合使用,共同完成属性变化的完整处理逻辑。

源码:

Source/CC_Aura/Public/AbilitySystem/CC_AttributeSet.h:

// 版权归陈超所有#pragma once#include \"CoreMinimal.h\"#include \"AbilitySystemComponent.h\"#include \"AttributeSet.h\"#include \"CC_AttributeSet.generated.h\"// * 要在游戏中使用它,您可以定义类似这样的内容,然后根据需要添加特定于游戏的功能:#define ATTRIBUTE_ACCESSORS(ClassName, PropertyName) \\GAMEPLAYATTRIBUTE_PROPERTY_GETTER(ClassName, PropertyName) \\GAMEPLAYATTRIBUTE_VALUE_GETTER(PropertyName) \\GAMEPLAYATTRIBUTE_VALUE_SETTER(PropertyName) \\GAMEPLAYATTRIBUTE_VALUE_INITTER(PropertyName)/** * */UCLASS()class CC_AURA_API UCC_AttributeSet : public UAttributeSet{GENERATED_BODY()public:UCC_AttributeSet();virtual void PreAttributeChange(const FGameplayAttribute& Attribute, float& NewValue) override;/**************************************************************************************************************//** 主要属性 **//**************************************************************************************************************/// 用于声明哪些变量需要在服务器和客户端之间自动复制‌virtual void GetLifetimeReplicatedProps(TArray& OutLifetimeProps) const override;/**********************************************************************/UPROPERTY(BlueprintReadOnly, Category=\"Vital Attributes\", ReplicatedUsing = OnRep_Health)FGameplayAttributeData Health;ATTRIBUTE_ACCESSORS(UCC_AttributeSet, Health);UPROPERTY(BlueprintReadOnly, Category=\"Vital Attributes\", ReplicatedUsing = OnRep_MaxHealth)FGameplayAttributeData MaxHealth;ATTRIBUTE_ACCESSORS(UCC_AttributeSet, MaxHealth);UPROPERTY(BlueprintReadOnly, Category=\"Vital Attributes\", ReplicatedUsing = OnRep_Mana)FGameplayAttributeData Mana;ATTRIBUTE_ACCESSORS(UCC_AttributeSet, Mana);UPROPERTY(BlueprintReadOnly, Category=\"Vital Attributes\", ReplicatedUsing = OnRep_MaxMana)FGameplayAttributeData MaxMana;ATTRIBUTE_ACCESSORS(UCC_AttributeSet, MaxMana);/**********************************************************************/UFUNCTION()void OnRep_Health(const FGameplayAttributeData& OldHealth) const;UFUNCTION()void OnRep_MaxHealth(const FGameplayAttributeData& OldMaxHealth) const;UFUNCTION()void OnRep_Mana(const FGameplayAttributeData& OldMana) const;UFUNCTION()void OnRep_MaxMana(const FGameplayAttributeData& OldMaxMana) const;/**************************************************************************************************************/};

Source/CC_Aura/Private/AbilitySystem/CC_AttributeSet.cpp:

// 版权归陈超所有#include \"AbilitySystem/CC_AttributeSet.h\"#include \"Net/UnrealNetwork.h\"UCC_AttributeSet::UCC_AttributeSet(){InitHealth(45.f);InitMaxHealth(100.f);InitMana(50.f);InitMaxMana(100.f);}void UCC_AttributeSet::PreAttributeChange(const FGameplayAttribute& Attribute, float& NewValue){Super::PreAttributeChange(Attribute, NewValue);if (Attribute == GetHealthAttribute()){NewValue = FMath::Clamp(NewValue, 0.f, GetMaxHealth());}if (Attribute == GetManaAttribute()){NewValue = FMath::Clamp(NewValue, 0.f, GetMaxMana());}}//将游戏玩法属性添加到属性集源文件中的GetLifetimeReplicatedProps函数中void UCC_AttributeSet::GetLifetimeReplicatedProps(TArray& OutLifetimeProps) const{Super::GetLifetimeReplicatedProps(OutLifetimeProps);// 为生命值添加复制功能。DOREPLIFETIME_CONDITION_NOTIFY(UCC_AttributeSet, Health, COND_None, REPNOTIFY_Always);// 为最大生命值添加复制功能。DOREPLIFETIME_CONDITION_NOTIFY(UCC_AttributeSet, MaxHealth, COND_None, REPNOTIFY_Always);// 为魔法值添加复制功能。DOREPLIFETIME_CONDITION_NOTIFY(UCC_AttributeSet, Mana, COND_None, REPNOTIFY_Always);// 为最大魔法值添加复制功能。DOREPLIFETIME_CONDITION_NOTIFY(UCC_AttributeSet, MaxMana, COND_None, REPNOTIFY_Always);}//~Begin 属性复制回调函数void UCC_AttributeSet::OnRep_Health(const FGameplayAttributeData& OldHealth) const{// 使用默认的游戏玩法属性系统更新通知行为。GAMEPLAYATTRIBUTE_REPNOTIFY(UCC_AttributeSet, Health, OldHealth);}void UCC_AttributeSet::OnRep_MaxHealth(const FGameplayAttributeData& OldMaxHealth) const{// 使用默认的游戏玩法属性系统更新通知行为。GAMEPLAYATTRIBUTE_REPNOTIFY(UCC_AttributeSet, MaxHealth, OldMaxHealth);}void UCC_AttributeSet::OnRep_Mana(const FGameplayAttributeData& OldMana) const{// 使用默认的游戏玩法属性系统更新通知行为。GAMEPLAYATTRIBUTE_REPNOTIFY(UCC_AttributeSet, Mana, OldMana);}void UCC_AttributeSet::OnRep_MaxMana(const FGameplayAttributeData& OldMaxMana) const{// 使用默认的游戏玩法属性系统更新通知行为。GAMEPLAYATTRIBUTE_REPNOTIFY(UCC_AttributeSet, MaxMana, OldMaxMana);}//~End 属性复制回调函数