13.3 GAS与属性

1. 属性的位置 —— 属性集

创建属性集类GASAttributeSet,继承自GAS提供的AttributeSet,并添加生命值相关的关键属性:

#pragma once

#include "CoreMinimal.h"
#include "AbilitySystemComponent.h"
#include "AttributeSet.h"
#include "GASAttributeSet.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 INSIDEGAS_API UGASAttributeSet : public UAttributeSet
{
    
    
	GENERATED_BODY()

public:
	UGASAttributeSet();

	virtual void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override;

public:
	UPROPERTY(BlueprintReadOnly, Category = "Health", ReplicatedUsing = OnRep_Health)
	FGameplayAttributeData Health;
	ATTRIBUTE_ACCESSORS(UGASAttributeSet, Health)

	UPROPERTY(BlueprintReadOnly, Category = "Health", ReplicatedUsing = OnRep_MaxHealth)
	FGameplayAttributeData MaxHealth;
	ATTRIBUTE_ACCESSORS(UGASAttributeSet, MaxHealth)

	UPROPERTY(BlueprintReadOnly, Category = "Health", ReplicatedUsing = OnRep_HealthRegenRate)
	FGameplayAttributeData HealthRegenRate;
	ATTRIBUTE_ACCESSORS(UGASAttributeSet, HealthRegenRate)

	UFUNCTION()
	virtual void OnRep_Health(const FGameplayAttributeData& OldHealth);

	UFUNCTION()
	virtual void OnRep_MaxHealth(const FGameplayAttributeData& OldMaxHealth);

	UFUNCTION()
	virtual void OnRep_HealthRegenRate(const FGameplayAttributeData& OldHealthRegenRate);
};
#include "GASAttributeSet.h"
#include "GameplayEffectExtension.h"
#include "Net/UnrealNetwork.h"

UGASAttributeSet::UGASAttributeSet()
{
    
    
}

void UGASAttributeSet::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
{
    
    
	Super::GetLifetimeReplicatedProps(OutLifetimeProps);

	DOREPLIFETIME_CONDITION_NOTIFY(UGASAttributeSet, Health, COND_None, REPNOTIFY_Always);
}

void UGASAttributeSet::OnRep_Health(const FGameplayAttributeData& OldHealth)
{
    
    
	GAMEPLAYATTRIBUTE_REPNOTIFY(UGASAttributeSet, Health, OldHealth);
}

void UGASAttributeSet::OnRep_MaxHealth(const FGameplayAttributeData& OldMaxHealth)
{
    
    
	GAMEPLAYATTRIBUTE_REPNOTIFY(UGASAttributeSet, MaxHealth, OldMaxHealth);
}

void UGASAttributeSet::OnRep_HealthRegenRate(const FGameplayAttributeData& OldHealthRegenRate)
{
    
    
	GAMEPLAYATTRIBUTE_REPNOTIFY(UGASAttributeSet, HealthRegenRate, OldHealthRegenRate);
}

其中ATTRIBUTE_ACCESSORS是利用AttributeSet提供的一系列宏为属性自动生成一些便利的函数,如初始化器、访问器、设置器等等,其本质上就是免去了自己去手写这些函数的麻烦。

然后将属性集挂载到角色身上,即在角色类GASCharacterBase类中添加代码:

头文件

void OnHealthChanged(const FOnAttributeChangeData& OnAttributeChangeData);
void OnMaxHealthChanged(const FOnAttributeChangeData& OnAttributeChangeData);
void OnHealthRegenRateChanged(const FOnAttributeChangeData& OnAttributeChangeData);

UPROPERTY()
UGASAttributeSet* AttributeSet;

UFUNCTION(BlueprintCallable, Category = "GAS|Attributes")
float GetHealth() const;

UFUNCTION(BlueprintCallable, Category = "GAS|Attributes")
float GetMaxHealth() const;

UFUNCTION(BlueprintCallable, Category = "GAS|Attributes")
float GetHealthRegenRate() const;

并在cpp中添加:

AGASCharacterBase::AGASCharacterBase(const FObjectInitializer& ObjectInitializer)
	: Super(ObjectInitializer)
{
    
    
	...
	
	AttributeSet = CreateDefaultSubobject<UGASAttributeSet>(TEXT("AttributeSet"));
}

float AGASCharacterBase::GetHealth() const
{
    
    
	return AttributeSet->GetHealth();
}

float AGASCharacterBase::GetMaxHealth() const
{
    
    
	return AttributeSet->GetMaxHealth();
}

float AGASCharacterBase::GetHealthRegenRate() const
{
    
    
	return AttributeSet->GetHealthRegenRate();
}

这样,就实现了角色挂载属性集,属性集上维护了一系列属性。此时编译并运行编辑器,打开GAS的调试信息,可以看到属性以及正确挂载到角色身上。

在这里插入图片描述

2. 属性的变化

属性得有数值其本身也具备意义,而赋值(如初始化)的实现方法有非常灵活,可以利用前面AttributeSet提供的初始化方法:

AttributeSet->InitHealth(100.0f);

也可以直接利用GE来进行初始化(GE也是与属性部分关系最为密切的模块):

扫描二维码关注公众号,回复: 14595659 查看本文章

在这里插入图片描述
在游玩开始时进行应用即可:

在这里插入图片描述

此时角色身上的属性就具备了初始值:

在这里插入图片描述

3. 简单的DOT伤害示例

这里我们使用HealthRegenRate属性来制作一个简单的掉血Buff(当然这不是这个属性设计的目的,这里更多是演示属性与GE的联合使用)。

创建生命值流失的GE:

在这里插入图片描述
其中Coefficent值设置为-2,他会和HealthRegenRate共同作用,以Period为周期,持续为Health属性做减法运算。同样,在将GE应用给角色的GAS组件:

在这里插入图片描述
并辅以UI控件(ProgressBar):

在这里插入图片描述
这样,一个简易的血条及掉血演示就完成了

在这里插入图片描述

4. 完善

在完成上面的测试后,很容易发现,血量在减到0后,依然不会停止。因为这显然并不合理。当然,我们可以通过卸载GE来停止这个Buff,但GAS提供了更加方便的接口,令我们可以直接对属性的变化做出限制。

在属性集类GASAttributeSet中重载PostGameplayEffectExecute

virtual void PostGameplayEffectExecute(const FGameplayEffectModCallbackData& Data) override;

void UGASAttributeSet::PostGameplayEffectExecute(const FGameplayEffectModCallbackData& Data)
{
    
    
	Super::PostGameplayEffectExecute(Data);

	if (Data.EvaluatedData.Attribute == GetHealthAttribute())
	{
    
    
		SetHealth(FMath::Clamp(GetHealth(), 0.0f, GetMaxHealth()));
	} 
}

如此进行简单的限制,保证血量不会跌破下限,也不会因为各种增益buff而突破上限。

参考:

属性 - Attributes

属性集 - Attribute Set

游戏效果 - Gameplay Effects

猜你喜欢

转载自blog.csdn.net/xcinkey/article/details/127775215
gas