UE4 UE4 C++ Gameplay Abilities 的AttributeSet和GameplayEffect
GAS参考文档
仅是个人理解,参考
AttributeSet是设置玩家属性的比如生命值、最大生命值、、、
GameplayEffect是用来对AttributeSet里的值做修改的
通过这两个东西做到:
一个加血的效果
先给玩家设置血量属性 做一个继承AttributeSet的类
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "AbilitySystemComponent.h"
#include "AttributeSet.h"
#include "MyAttributeSet.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 MYGAS_API UMyAttributeSet : public UAttributeSet
{
GENERATED_BODY()
public:
UPROPERTY(BlueprintReadOnly)
FGameplayAttributeData Health;
ATTRIBUTE_ACCESSORS(UMyAttributeSet, Health)
UPROPERTY(BlueprintReadOnly)
FGameplayAttributeData MaxHealth;
ATTRIBUTE_ACCESSORS(UMyAttributeSet, MaxHealth)
UPROPERTY(BlueprintReadOnly)
FGameplayAttributeData Damage;
ATTRIBUTE_ACCESSORS(UMyAttributeSet, Damage)
//更改之前会调用
virtual void PreAttributeChange(const FGameplayAttribute& Attribute, float& NewValue) override;
//更改之后
virtual void PostGameplayEffectExecute(const FGameplayEffectModCallbackData& Data) override;
protected:
void AdjustAttributeForMaxChange(FGameplayAttributeData& AffectedAttribute, const FGameplayAttributeData& MaxAttribute, float NewMaxValue, const FGameplayAttribute& AffectedAttributeProperty);
};
// Fill out your copyright notice in the Description page of Project Settings.
#include "GAS/MyAttributeSet.h"
#include "GameplayEffectExtension.h"
#include "MyGAS/MyGASCharacter.h"
void UMyAttributeSet::PreAttributeChange(const FGameplayAttribute& Attribute, float& NewValue)
{
Super::PreAttributeChange(Attribute, NewValue);
/*GetMaxHealthAttribute() 这个要给变量加了ATTRIBUTE_ACCESSORS(UMyAttributeSet, MaxHealth) 这个宏才可以调用*/
if (Attribute == GetMaxHealthAttribute())
{
AdjustAttributeForMaxChange(Health, MaxHealth, NewValue, GetHealthAttribute());
}
}
void UMyAttributeSet::PostGameplayEffectExecute(const FGameplayEffectModCallbackData& Data)
{
if (Data.EvaluatedData.Attribute == GetHealthAttribute())
{
SetHealth(FMath::Clamp(GetHealth(), 0.0f, GetMaxHealth()));
}
else if (Data.EvaluatedData.Attribute == GetDamageAttribute())
{
float CurrentDamage = GetDamage();
if (CurrentDamage > 0)
{
SetDamage(0);
SetHealth(FMath::Clamp(GetHealth() - CurrentDamage, 0.0f, GetMaxHealth()));
AActor* TargetActor = Data.Target.AbilityActorInfo->AvatarActor.Get();
AMyGASCharacter* TargetCharacter = Cast<AMyGASCharacter>(TargetActor);
TargetCharacter->OnDamaged(CurrentDamage);
}
}
}
void UMyAttributeSet::AdjustAttributeForMaxChange(FGameplayAttributeData& AffectedAttribute,
const FGameplayAttributeData& MaxAttribute, float NewMaxValue, const FGameplayAttribute& AffectedAttributeProperty)
{
UAbilitySystemComponent* AbilityComp = GetOwningAbilitySystemComponent();
const float CurrentMaxValue = MaxAttribute.GetCurrentValue();
if (!FMath::IsNearlyEqual(CurrentMaxValue, NewMaxValue) && AbilityComp)
{
// Change current value to maintain the current Val / Max percent
const float CurrentValue = AffectedAttribute.GetCurrentValue();
float NewDelta = (CurrentMaxValue > 0.f) ? (CurrentValue * NewMaxValue / CurrentMaxValue) - CurrentValue : NewMaxValue;
AbilityComp->ApplyModToAttributeUnsafe(AffectedAttributeProperty, EGameplayModOp::Additive, NewDelta);
}
}
把这个类初始化到玩家的类里面
像组件一样初始化好就行了
做血条UI
绑定血条的百分比
只有在玩家类里初始化了AttributeSet类才可以拿到
给玩家血条设置初始值
新建一个蓝图类的GameplayEffect:
设置好最大值和当前生命值
在玩家里调用就设置好了初始值
再搞个给玩家加血的GameplayEffect:
这里用到了一个曲线表格:
我们延迟一秒给玩家加50滴血
如果没有曲线表格,就在GE_Add 里面的1数字改为50
只是Level 那里填的50 就没有效果了