虚幻引擎5 GAS开发俯视角RPG游戏 P06-31 映射标签到属性

1.在小部件里添加标签,当标签一致时,修改对应的结果:

细节:

2.在属性集里添加映射CC_AttributeSet.h

Map(标签, 获取属性的方法指针)

cpp 复制代码
/*
 * 模板函数:
 * 别名: 静态函数指针
 * 用途: 1. TMap(指针,属性)
 */
template<class T>
using TStaticFuncPtr = typename TBaseStaticDelegateInstance<T, FDefaultDelegateUserPolicy>::FFuncPtr;
cpp 复制代码
	/*
	 * TMap(指针,属性)
	 */
	TMap<FGameplayTag, TStaticFuncPtr<FGameplayAttribute()>> TagsToAttributes;

这段代码定义了虚幻引擎5 GAS系统中用于将游戏标签映射到属性访问函数的类型声明。

TStaticFuncPtr是一个模板别名,它指向TBaseStaticDelegateInstance的静态函数指针类型FFuncPtr,这是UE委托系统中用于绑定静态函数的核心类型。

TagsToAttributes是一个TMap容器,键为FGameplayTag游戏标签,值为返回FGameplayAttribute的静态函数指针。这种设计允许通过游戏标签动态查找对应的属性访问函数,为属性菜单UI提供数据支持。

在属性集构造函数里添加映射CC_AttributeSet.cpp:

cpp 复制代码
UCC_AttributeSet::UCC_AttributeSet()
{
	TagsToAttributes.Add(CC_GameplayTags::Attributes_Primary_Agile, GetAgileAttribute);
	TagsToAttributes.Add(CC_GameplayTags::Attributes_Primary_Intelligence, GetIntelligenceAttribute);
	TagsToAttributes.Add(CC_GameplayTags::Attributes_Primary_Strength, GetStrengthAttribute);
	TagsToAttributes.Add(CC_GameplayTags::Attributes_Primary_Vigor, GetVigorAttribute);
	
	TagsToAttributes.Add(CC_GameplayTags::Attributes_Secondary_Armor, GetArmorAttribute);
	TagsToAttributes.Add(CC_GameplayTags::Attributes_Secondary_ArmorPenetration, GetArmorPenetrationAttribute);
	TagsToAttributes.Add(CC_GameplayTags::Attributes_Secondary_BlockChance, GetBlockChanceAttribute);
	TagsToAttributes.Add(CC_GameplayTags::Attributes_Secondary_CriticalHitChance, GetCriticalHitChanceAttribute);
	TagsToAttributes.Add(CC_GameplayTags::Attributes_Secondary_CriticalHitDamage, GetCriticalHitDamageAttribute);
	TagsToAttributes.Add(CC_GameplayTags::Attributes_Secondary_CriticalHitResistance, GetCriticalHitResistanceAttribute);
	TagsToAttributes.Add(CC_GameplayTags::Attributes_Secondary_HealthRegeneration, GetHealthRegenerationAttribute);
	TagsToAttributes.Add(CC_GameplayTags::Attributes_Secondary_ManaRegeneration, GetManaRegenerationAttribute);
	TagsToAttributes.Add(CC_GameplayTags::Attributes_Secondary_MaxHealth, GetMaxHealthAttribute);
	TagsToAttributes.Add(CC_GameplayTags::Attributes_Secondary_MaxMana, GetMaxManaAttribute);

}

3.在CC_AttributeMenuWidgetController.cpp的BroadcastInitialValues方法里:

cpp 复制代码
void UCC_AttributeMenuWidgetController::BroadcastInitialValues()
{
	if (CC_AttributeSet == nullptr)
	{
		CC_AttributeSet = CastChecked<UCC_AttributeSet>(AttributeSet);
	}
	checkf(AttributeInfo, TEXT("在[%s]中没有配置AttributeInfo"), *GetNameSafe(this));

	for (auto& Pair : CC_AttributeSet->TagsToAttributes)
	{
		FAttributeInfo Info = AttributeInfo->FindAttributeInfoFromTag(Pair.Key);
		Info.AttributeValue = Pair.Value().GetNumericValue(CC_AttributeSet);
		OnAttributeInfoSignature.Broadcast(Info);
	}
}

这段代码实现了虚幻引擎5 GAS中属性菜单小部件控制器的初始值广播功能。

首先检查属性集是否为空,如果为空则通过类型转换获取属性集实例。接着验证AttributeInfo数据资产是否有效,如果未配置则会触发断言错误。

核心逻辑是遍历属性集中的TagsToAttributes映射,为每个属性标签查找对应的属性信息配置。通过GetNumericValue方法获取属性集的当前数值,并将其设置到属性信息结构中。最后通过OnAttributeInfoSignature委托广播更新后的属性信息,通知UI组件进行相应更新。

该函数通常在WidgetController初始化时调用,确保UI能够正确显示所有属性的初始数值。

效果:

源码:

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

cpp 复制代码
// 版权归陈超所有

#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)

/*用于存储施放GE的相关对象和目标的相关对象*/
#pragma region FEffectProperties

USTRUCT()
struct FEffectProperties
{
	GENERATED_BODY()

	FEffectProperties(){}

	FGameplayEffectContextHandle EffectContextHandle;
	
	UPROPERTY()
	UAbilitySystemComponent* SourceASC = nullptr;

	UPROPERTY()
	AActor* SourceAvatarActor = nullptr;

	UPROPERTY()
	AController* SourceController = nullptr;

	UPROPERTY()
	ACharacter* SourceCharacter = nullptr;
	
	UPROPERTY()
	UAbilitySystemComponent* TargetASC = nullptr;

	UPROPERTY()
	AActor* TargetAvatarActor = nullptr;

	UPROPERTY()
	AController* TargetController = nullptr;

	UPROPERTY()
	ACharacter* TargetCharacter = nullptr;
};

#pragma endregion

/*
 * 模板函数:
 * 别名: 静态函数指针
 * 用途: 1. TMap(指针,属性)
 */
template<class T>
using TStaticFuncPtr = typename TBaseStaticDelegateInstance<T, FDefaultDelegateUserPolicy>::FFuncPtr;

/**
 * 
 */
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 PostGameplayEffectExecute(const struct FGameplayEffectModCallbackData& Data) override;

	/*
	 * TMap(指针,属性)
	 */
	TMap<FGameplayTag, TStaticFuncPtr<FGameplayAttribute()>> TagsToAttributes;

	
private:
	void SetEffectProperties(const struct FGameplayEffectModCallbackData& Data, FEffectProperties& Props) const;
/**************************************************************************************************************/
/**                                                     添加属性                                               **/
/**************************************************************************************************************/
public:
	// 用于声明哪些变量需要在服务器和客户端之间自动复制‌
	virtual void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override;

/*Vital属性:
*		1.获取角色等级
*/
#pragma region Vital Attributes
	UPROPERTY(BlueprintReadOnly, Category="Attributes|Vital", ReplicatedUsing = OnRep_Health)
	FGameplayAttributeData Health;
	ATTRIBUTE_ACCESSORS(UCC_AttributeSet, Health);

	UPROPERTY(BlueprintReadOnly, Category="Attributes|Vital", ReplicatedUsing = OnRep_Mana)
	FGameplayAttributeData Mana;
	ATTRIBUTE_ACCESSORS(UCC_AttributeSet, Mana);

#pragma endregion


/**********************************************************************/

/*主要属性
	*1. Vigor: 体质
	*2. Agile: 敏捷
	*3. Strength: 力量
	*4. Intelligence: 智力
*/
#pragma region Primary Attributes
		
	UPROPERTY(BlueprintReadOnly, Category="Attributes|Primary", ReplicatedUsing = OnRep_Vigor)
	FGameplayAttributeData Vigor;
	ATTRIBUTE_ACCESSORS(UCC_AttributeSet, Vigor);
	
	UPROPERTY(BlueprintReadOnly, Category="Attributes|Primary", ReplicatedUsing = OnRep_Agile)
	FGameplayAttributeData Agile;
	ATTRIBUTE_ACCESSORS(UCC_AttributeSet, Agile);
		
	UPROPERTY(BlueprintReadOnly, Category="Attributes|Primary", ReplicatedUsing = OnRep_Strength)
	FGameplayAttributeData Strength;
	ATTRIBUTE_ACCESSORS(UCC_AttributeSet, Strength);
	
	UPROPERTY(BlueprintReadOnly, Category="Attributes|Primary", ReplicatedUsing = OnRep_Intelligence)
	FGameplayAttributeData Intelligence;
	ATTRIBUTE_ACCESSORS(UCC_AttributeSet, Intelligence);

#pragma endregion

/*次要属性:
 * 1. Armor: 护甲	减少受到的伤害, 提高格挡几率.
 *		- 受Agile影响
 *
 * 2. Armor Penetration: 护甲穿透	忽略敌人护甲的百分比, 增加暴击几率.
 *		- 受Agile影响
 *
 * 3. Block Chance: 格挡几率		有机会将受到的伤害减半.
 *		- 受Armor影响
 *
 * 4. Critical Hit Chance: 暴击几率		有机会获得双倍伤害并获得暴击加成
 *		- 受Armor Penetration影响
 *
 * 5. Critical Hit Damage: 暴击伤害		暴击时增加的额外伤害
 *		- 受Armor Penetration影响
 *
 * 6. Critical Hit Resistance: 暴击抗性		减少敌人攻击时的暴击几率
 *		- 受Armor影响
 *
 * 7. Health Regeneration: 生命回复		每秒回复的生命值
 *		- 受Vigor影响
 *
 * 8. Mana Regeneration: 魔法回复		每秒回复的魔法值
 *		- 受Intelligence影响
 *
 * 9. Max Health: 最大生命值
 *		- 受Vigor影响
 *
 * 10. Max Mana: 最大法力值
 *		- 受Intelligence影响
 */
	
#pragma region Secondary Attributes

	UPROPERTY(BlueprintReadOnly, Category="Attributes|Secondary", ReplicatedUsing = OnRep_Armor)
	FGameplayAttributeData Armor;
	ATTRIBUTE_ACCESSORS(UCC_AttributeSet, Armor);
		
	UPROPERTY(BlueprintReadOnly, Category="Attributes|Secondary", ReplicatedUsing = OnRep_ArmorPenetration)
	FGameplayAttributeData ArmorPenetration;
	ATTRIBUTE_ACCESSORS(UCC_AttributeSet, ArmorPenetration);
		
	UPROPERTY(BlueprintReadOnly, Category="Attributes|Secondary", ReplicatedUsing = OnRep_BlockChance)
	FGameplayAttributeData BlockChance;
	ATTRIBUTE_ACCESSORS(UCC_AttributeSet, BlockChance);
	
	UPROPERTY(BlueprintReadOnly, Category="Attributes|Secondary", ReplicatedUsing = OnRep_CriticalHitChance)
	FGameplayAttributeData CriticalHitChance;
	ATTRIBUTE_ACCESSORS(UCC_AttributeSet, CriticalHitChance);

	UPROPERTY(BlueprintReadOnly, Category="Attributes|Secondary", ReplicatedUsing = OnRep_CriticalHitDamage)
	FGameplayAttributeData CriticalHitDamage;
	ATTRIBUTE_ACCESSORS(UCC_AttributeSet, CriticalHitDamage);

	UPROPERTY(BlueprintReadOnly, Category="Attributes|Secondary", ReplicatedUsing = OnRep_CriticalHitResistance)
	FGameplayAttributeData CriticalHitResistance;
	ATTRIBUTE_ACCESSORS(UCC_AttributeSet, CriticalHitResistance);

	UPROPERTY(BlueprintReadOnly, Category="Attributes|Secondary", ReplicatedUsing = OnRep_HealthRegeneration)
	FGameplayAttributeData HealthRegeneration;
	ATTRIBUTE_ACCESSORS(UCC_AttributeSet, HealthRegeneration);

	UPROPERTY(BlueprintReadOnly, Category="Attributes|Secondary", ReplicatedUsing = OnRep_ManaRegeneration)
	FGameplayAttributeData ManaRegeneration;
	ATTRIBUTE_ACCESSORS(UCC_AttributeSet, ManaRegeneration);
	
	UPROPERTY(BlueprintReadOnly, Category="Attributes|Secondary", ReplicatedUsing = OnRep_MaxHealth)
	FGameplayAttributeData MaxHealth;
	ATTRIBUTE_ACCESSORS(UCC_AttributeSet, MaxHealth);
	
	UPROPERTY(BlueprintReadOnly, Category="Attributes|Secondary", ReplicatedUsing = OnRep_MaxMana)
	FGameplayAttributeData MaxMana;
	ATTRIBUTE_ACCESSORS(UCC_AttributeSet, MaxMana);

#pragma endregion
	
/*********************************************************************
 * 复制回调函数
 */
#pragma region OnRep_Fuc
	
	UFUNCTION()
	void OnRep_ManaRegeneration(const FGameplayAttributeData& OldValue) const;
	
	UFUNCTION()
	void OnRep_HealthRegeneration(const FGameplayAttributeData& OldValue) const;
	
	UFUNCTION()
	void OnRep_CriticalHitResistance(const FGameplayAttributeData& OldValue) const;
	
	UFUNCTION()
	void OnRep_CriticalHitDamage(const FGameplayAttributeData& OldValue) const;
	
	UFUNCTION()
	void OnRep_CriticalHitChance(const FGameplayAttributeData& OldValue) const;
	
	UFUNCTION()
	void OnRep_BlockChance(const FGameplayAttributeData& OldValue) const;
	
	UFUNCTION()
	void OnRep_ArmorPenetration(const FGameplayAttributeData& OldValue) const;
	
	UFUNCTION()
	void OnRep_Armor(const FGameplayAttributeData& OldValue) const;
	
	UFUNCTION()
	void OnRep_Health(const FGameplayAttributeData& OldValue) const;

	UFUNCTION()
	void OnRep_MaxHealth(const FGameplayAttributeData& OldValue) const;

	UFUNCTION()
	void OnRep_Mana(const FGameplayAttributeData& OldValue) const;

	UFUNCTION()
	void OnRep_MaxMana(const FGameplayAttributeData& OldValue) const;
	
	UFUNCTION()
	void OnRep_Intelligence(const FGameplayAttributeData& OldValue) const;

	UFUNCTION()
	void OnRep_Agile(const FGameplayAttributeData& OldValue) const;
	
	UFUNCTION()
	void OnRep_Strength(const FGameplayAttributeData& OldValue) const;
		
	UFUNCTION()
	void OnRep_Vigor(const FGameplayAttributeData& OldValue) const;
	
#pragma endregion
	
/**************************************************************************************************************/
};

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

cpp 复制代码
// 版权归陈超所有


#include "AbilitySystem/CC_AttributeSet.h"

#include "AbilitySystemBlueprintLibrary.h"
#include "CC_GameplayTags.h"
#include "Net/UnrealNetwork.h"
#include "GameplayEffectExtension.h"  // 包含FGameplayEffectModCallbackData定义
#include "GameFramework/Character.h"


UCC_AttributeSet::UCC_AttributeSet()
{
	TagsToAttributes.Add(CC_GameplayTags::Attributes_Primary_Agile, GetAgileAttribute);
	TagsToAttributes.Add(CC_GameplayTags::Attributes_Primary_Intelligence, GetIntelligenceAttribute);
	TagsToAttributes.Add(CC_GameplayTags::Attributes_Primary_Strength, GetStrengthAttribute);
	TagsToAttributes.Add(CC_GameplayTags::Attributes_Primary_Vigor, GetVigorAttribute);
	
	TagsToAttributes.Add(CC_GameplayTags::Attributes_Secondary_Armor, GetArmorAttribute);
	TagsToAttributes.Add(CC_GameplayTags::Attributes_Secondary_ArmorPenetration, GetArmorPenetrationAttribute);
	TagsToAttributes.Add(CC_GameplayTags::Attributes_Secondary_BlockChance, GetBlockChanceAttribute);
	TagsToAttributes.Add(CC_GameplayTags::Attributes_Secondary_CriticalHitChance, GetCriticalHitChanceAttribute);
	TagsToAttributes.Add(CC_GameplayTags::Attributes_Secondary_CriticalHitDamage, GetCriticalHitDamageAttribute);
	TagsToAttributes.Add(CC_GameplayTags::Attributes_Secondary_CriticalHitResistance, GetCriticalHitResistanceAttribute);
	TagsToAttributes.Add(CC_GameplayTags::Attributes_Secondary_HealthRegeneration, GetHealthRegenerationAttribute);
	TagsToAttributes.Add(CC_GameplayTags::Attributes_Secondary_ManaRegeneration, GetManaRegenerationAttribute);
	TagsToAttributes.Add(CC_GameplayTags::Attributes_Secondary_MaxHealth, GetMaxHealthAttribute);
	TagsToAttributes.Add(CC_GameplayTags::Attributes_Secondary_MaxMana, GetMaxManaAttribute);

}

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());
	}
}

void UCC_AttributeSet::PostGameplayEffectExecute(const struct FGameplayEffectModCallbackData& Data)
{
	Super::PostGameplayEffectExecute(Data);
	
	FEffectProperties Props;
	SetEffectProperties(Data, Props);
	
	if(Data.EvaluatedData.Attribute == GetHealthAttribute())
	{
		SetHealth(FMath::Clamp(GetHealth(), 0.f, GetMaxHealth()));
	}

	if(Data.EvaluatedData.Attribute == GetManaAttribute())
	{
		SetMana(FMath::Clamp(GetMana(), 0.f, GetMaxMana()));
	}
	
}

void UCC_AttributeSet::SetEffectProperties(const struct FGameplayEffectModCallbackData& Data, FEffectProperties& Props) const
{
	Props.EffectContextHandle = Data.EffectSpec.GetContext();
	
	//获取效果所有者的相关对象
	Props.SourceASC = Props.EffectContextHandle.GetOriginalInstigatorAbilitySystemComponent();	//获取SourceASC
	if(IsValid(Props.SourceASC) && Props.SourceASC->AbilityActorInfo.IsValid() && Props.SourceASC->AbilityActorInfo->AvatarActor.IsValid())
	{
		Props.SourceAvatarActor = Props.SourceASC->AbilityActorInfo->AvatarActor.Get();			//获取SourceAvatarActor
		Props.SourceController = Props.SourceASC->AbilityActorInfo->PlayerController.Get();		//获取SourceController
		if(Props.SourceController == nullptr && Props.SourceAvatarActor != nullptr)
		{
			if(const APawn* Pawn = Cast<APawn>(Props.SourceAvatarActor))
			{
				Props.SourceController = Pawn->GetController();
			}
		}

		if(Props.SourceController)
		{
			Props.SourceCharacter = Cast<ACharacter>(Props.SourceController->GetPawn());	//获取SourceCharacter
		}
	}

	if(Data.Target.AbilityActorInfo.IsValid() && Data.Target.AbilityActorInfo->AvatarActor.IsValid())
	{
		Props.TargetAvatarActor = Data.Target.AbilityActorInfo->AvatarActor.Get();
		Props.TargetController = Data.Target.AbilityActorInfo->PlayerController.Get();
		Props.TargetCharacter = Cast<ACharacter>(Props.TargetAvatarActor);
		Props.TargetASC = UAbilitySystemBlueprintLibrary::GetAbilitySystemComponent(Props.TargetAvatarActor);
	}	
}

//将游戏玩法属性添加到属性集源文件中的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);
	
	DOREPLIFETIME_CONDITION_NOTIFY(UCC_AttributeSet, Intelligence, COND_None, REPNOTIFY_Always);
	
	DOREPLIFETIME_CONDITION_NOTIFY(UCC_AttributeSet, Agile, COND_None, REPNOTIFY_Always);
	
	DOREPLIFETIME_CONDITION_NOTIFY(UCC_AttributeSet, Strength, COND_None, REPNOTIFY_Always);
	
	DOREPLIFETIME_CONDITION_NOTIFY(UCC_AttributeSet, Vigor, COND_None, REPNOTIFY_Always);
	
	DOREPLIFETIME_CONDITION_NOTIFY(UCC_AttributeSet, Armor, COND_None, REPNOTIFY_Always);
	
	DOREPLIFETIME_CONDITION_NOTIFY(UCC_AttributeSet, ArmorPenetration, COND_None, REPNOTIFY_Always);
	
	DOREPLIFETIME_CONDITION_NOTIFY(UCC_AttributeSet, BlockChance, COND_None, REPNOTIFY_Always);
	
	DOREPLIFETIME_CONDITION_NOTIFY(UCC_AttributeSet, CriticalHitChance, COND_None, REPNOTIFY_Always);
	
	DOREPLIFETIME_CONDITION_NOTIFY(UCC_AttributeSet, CriticalHitDamage, COND_None, REPNOTIFY_Always);
	
	DOREPLIFETIME_CONDITION_NOTIFY(UCC_AttributeSet, CriticalHitResistance, COND_None, REPNOTIFY_Always);
	
	DOREPLIFETIME_CONDITION_NOTIFY(UCC_AttributeSet, HealthRegeneration, COND_None, REPNOTIFY_Always);
	
	DOREPLIFETIME_CONDITION_NOTIFY(UCC_AttributeSet, ManaRegeneration, COND_None, REPNOTIFY_Always);
	
}

void UCC_AttributeSet::OnRep_ManaRegeneration(const FGameplayAttributeData& OldValue) const
{
	GAMEPLAYATTRIBUTE_REPNOTIFY(UCC_AttributeSet, ManaRegeneration, OldValue);
}

void UCC_AttributeSet::OnRep_HealthRegeneration(const FGameplayAttributeData& OldValue) const
{
	GAMEPLAYATTRIBUTE_REPNOTIFY(UCC_AttributeSet, HealthRegeneration, OldValue);
}

void UCC_AttributeSet::OnRep_CriticalHitResistance(const FGameplayAttributeData& OldValue) const
{
	GAMEPLAYATTRIBUTE_REPNOTIFY(UCC_AttributeSet, CriticalHitResistance, OldValue);
}

void UCC_AttributeSet::OnRep_CriticalHitDamage(const FGameplayAttributeData& OldValue) const
{
	GAMEPLAYATTRIBUTE_REPNOTIFY(UCC_AttributeSet, CriticalHitDamage, OldValue);
}

void UCC_AttributeSet::OnRep_CriticalHitChance(const FGameplayAttributeData& OldValue) const
{
	GAMEPLAYATTRIBUTE_REPNOTIFY(UCC_AttributeSet, CriticalHitChance, OldValue);
}

void UCC_AttributeSet::OnRep_BlockChance(const FGameplayAttributeData& OldValue) const
{
	GAMEPLAYATTRIBUTE_REPNOTIFY(UCC_AttributeSet, BlockChance, OldValue);
}

void UCC_AttributeSet::OnRep_ArmorPenetration(const FGameplayAttributeData& OldValue) const
{
	GAMEPLAYATTRIBUTE_REPNOTIFY(UCC_AttributeSet, ArmorPenetration, OldValue);
}

void UCC_AttributeSet::OnRep_Armor(const FGameplayAttributeData& OldValue) const
{
	GAMEPLAYATTRIBUTE_REPNOTIFY(UCC_AttributeSet, Armor, OldValue);
}

//~Begin 属性复制回调函数
void UCC_AttributeSet::OnRep_Health(const FGameplayAttributeData& OldValue) const
{
	// 使用默认的游戏玩法属性系统更新通知行为。
	GAMEPLAYATTRIBUTE_REPNOTIFY(UCC_AttributeSet, Health, OldValue);
}

void UCC_AttributeSet::OnRep_MaxHealth(const FGameplayAttributeData& OldValue) const
{
	// 使用默认的游戏玩法属性系统更新通知行为。
	GAMEPLAYATTRIBUTE_REPNOTIFY(UCC_AttributeSet, MaxHealth, OldValue);
}

void UCC_AttributeSet::OnRep_Mana(const FGameplayAttributeData& OldValue) const
{
	// 使用默认的游戏玩法属性系统更新通知行为。
	GAMEPLAYATTRIBUTE_REPNOTIFY(UCC_AttributeSet, Mana, OldValue);
}

void UCC_AttributeSet::OnRep_MaxMana(const FGameplayAttributeData& OldValue) const
{
	// 使用默认的游戏玩法属性系统更新通知行为。
	GAMEPLAYATTRIBUTE_REPNOTIFY(UCC_AttributeSet, MaxMana, OldValue);
}

void UCC_AttributeSet::OnRep_Intelligence(const FGameplayAttributeData& OldValue) const
{
	GAMEPLAYATTRIBUTE_REPNOTIFY(UCC_AttributeSet, Intelligence, OldValue);
}

void UCC_AttributeSet::OnRep_Agile(const FGameplayAttributeData& OldValue) const
{
	GAMEPLAYATTRIBUTE_REPNOTIFY(UCC_AttributeSet, Agile, OldValue);
}

void UCC_AttributeSet::OnRep_Strength(const FGameplayAttributeData& OldValue) const
{
	GAMEPLAYATTRIBUTE_REPNOTIFY(UCC_AttributeSet, Strength, OldValue);
}

void UCC_AttributeSet::OnRep_Vigor(const FGameplayAttributeData& OldValue) const
{
	GAMEPLAYATTRIBUTE_REPNOTIFY(UCC_AttributeSet, Vigor, OldValue);
}

//~End 属性复制回调函数

Source/CC_Aura/Public/UI/WidgetController/CC_AttributeMenuWidgetController.h:

cpp 复制代码
// 版权归陈超所有

#pragma once

#include "CoreMinimal.h"
#include "UI/WidgetController/CC_WidgetController.h"
#include "CC_AttributeMenuWidgetController.generated.h"

class UCC_AttributeInfo;
struct FAttributeInfo;
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnAttributeInfoSignature, const FAttributeInfo&, Info);

/**
 * 
 */
UCLASS(Blueprintable)
class CC_AURA_API UCC_AttributeMenuWidgetController : public UCC_WidgetController
{
	GENERATED_BODY()

public:
	//广播初始值
	virtual void BroadcastInitialValues() override;

	//依赖的绑定回调函数
	virtual void BindCallbacksToDependencies() override;

protected:
	UPROPERTY(EditDefaultsOnly, Category="CC|GAS|Attributes")
	TObjectPtr<UCC_AttributeInfo> AttributeInfo;

	UPROPERTY(BlueprintAssignable, BlueprintReadWrite, Category="CC|GAS|Attributes")
	FOnAttributeInfoSignature OnAttributeInfoSignature;
	
};

Source/CC_Aura/Private/UI/WidgetController/CC_AttributeMenuWidgetController.cpp:

cpp 复制代码
// 版权归陈超所有


#include "UI/WidgetController/CC_AttributeMenuWidgetController.h"

#include "CC_GameplayTags.h"
#include "AbilitySystem/CC_AttributeSet.h"
#include "AbilitySystem/Data/CC_AttributeInfo.h"

void UCC_AttributeMenuWidgetController::BroadcastInitialValues()
{
	if (CC_AttributeSet == nullptr)
	{
		CC_AttributeSet = CastChecked<UCC_AttributeSet>(AttributeSet);
	}
	checkf(AttributeInfo, TEXT("在[%s]中没有配置AttributeInfo"), *GetNameSafe(this));

	for (auto& Pair : CC_AttributeSet->TagsToAttributes)
	{
		FAttributeInfo Info = AttributeInfo->FindAttributeInfoFromTag(Pair.Key);
		Info.AttributeValue = Pair.Value().GetNumericValue(CC_AttributeSet);
		OnAttributeInfoSignature.Broadcast(Info);
	}
}

void UCC_AttributeMenuWidgetController::BindCallbacksToDependencies()
{
	//属性发生变化时,希望也进行广播
	if (CC_AttributeSet == nullptr)
	{
		CC_AttributeSet = CastChecked<UCC_AttributeSet>(AttributeSet);
	}
	checkf(AttributeInfo, TEXT("在[%s]中没有配置AttributeInfo"), *GetNameSafe(this));

	for (auto& Pair : CC_AttributeSet->TagsToAttributes)
	{
		AbilitySystemComponent->GetGameplayAttributeValueChangeDelegate(Pair.Value()).AddLambda(
			[this, Pair](const FOnAttributeChangeData& Data)
			{
				FAttributeInfo Info = AttributeInfo->FindAttributeInfoFromTag(Pair.Key);
				Info.AttributeValue = Pair.Value().GetNumericValue(CC_AttributeSet);
				OnAttributeInfoSignature.Broadcast(Info);
			}
		);
	}
	
}
相关推荐
刃神太酷啦6 小时前
力扣校招算法通关:双指针技巧全场景拆解 —— 从数组操作到环检测的高效解题范式
java·c语言·数据结构·c++·算法·leetcode·职场和发展
gshh__7 小时前
SuperMap Hi-Fi 3D SDK for Unreal 使用蓝图接口加载多源数据
ue5·游戏引擎·supermap
haofafa7 小时前
STL之动态数组
开发语言·c++
leafff1237 小时前
AI研究:轻量模型和专用模型在算力优化上的差异对游戏制作的效率和质量有何影响?
人工智能·游戏
无敌最俊朗@8 小时前
梳理了音视频开发核心知识点
c++·音视频
专注VB编程开发20年8 小时前
.NET Reflector反编绎,如何移除DLL中的一个公开属性
开发语言·c++·c#
Howard在远程8 小时前
[编程农场][The Farmer Was Replaced]——Bones/Dinasour
python·游戏
落羽的落羽8 小时前
【Linux系统】C/C++的调试器gdb/cgdb,从入门到精通
linux·服务器·c语言·c++·人工智能·学习·机器学习
在下雨5998 小时前
条件变量与互斥锁复习
c++·面试