虚幻引擎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<FLifetimeProperty>& 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<FLifetimeProperty>& 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 属性复制回调函数

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值