创建技能图标UI类
// 幻雨喜欢小猫咪
#pragma once
#include "CoreMinimal.h"
#include "Blueprint/UserWidget.h"
#include "Components/Image.h"
#include "Components/TextBlock.h"
#include "AbilityGauge.generated.h"
/**
*
*/
UCLASS()
class CRUNCH_API UAbilityGauge : public UUserWidget
{
GENERATED_BODY()
private:
// 技能图标
UPROPERTY(meta = (BindWidget))
TObjectPtr<UImage> Icon;
// 冷却计时文本控件
UPROPERTY(meta=(BindWidget))
TObjectPtr<UTextBlock> CooldownCounterText;
// 冷却总时长文本控件
UPROPERTY(meta=(BindWidget))
TObjectPtr<UTextBlock> CooldownDurationText;
// 技能消耗文本控件
UPROPERTY(meta=(BindWidget))
TObjectPtr<UTextBlock> CostText;
};
放入cpp写好的控件
从角色中将技能表传递到UI中
在能力组件CAbilitySystemComponent
和CCharacter
角色基类中添加获取技能表的函数
const TMap<ECAbilityInputID, TSubclassOf<UGameplayAbility>>& GetAbilities() const;
const TMap<ECAbilityInputID, TSubclassOf<UGameplayAbility>>& UCAbilitySystemComponent::GetAbilities() const
{
return Abilities;
}
const TMap<ECAbilityInputID, TSubclassOf<UGameplayAbility>>& ACCharacter::GetAbilities() const
{
return CAbilitySystemComponent->GetAbilities();
}
GameplayWidget
创建一个获取技能表传递配置的函数
void ConfigureAbilities(const TMap<ECAbilityInputID, TSubclassOf<UGameplayAbility>>& Abilities);
在玩家控制器CPlayerController
中把技能表传递给UI
void ACPlayerController::SpawnGameplayWidget()
{
// 检查当前玩家控制器是否是本地玩家控制器
if (!IsLocalPlayerController()) return;
if (GameplayWidgetClass)
{
GameplayWidget = CreateWidget<UGameplayWidget>(this, GameplayWidgetClass);
if (GameplayWidget)
{
// 添加到视口中
GameplayWidget->AddToViewport();
// 将技能数据传递给UI
GameplayWidget->ConfigureAbilities(CPlayerCharacter->GetAbilities());
}
}
}
创建一个技能列表
// 幻雨喜欢小猫咪
#pragma once
#include "CoreMinimal.h"
#include "Components/ListView.h"
#include "GAS/Core/CGameplayAbilityTypes.h"
#include "AbilityListView.generated.h"
/**
*
*/
UCLASS()
class CRUNCH_API UAbilityListView : public UListView
{
GENERATED_BODY()
public:
// 配置能力表
void ConfigureAbilities(const TMap<ECAbilityInputID, TSubclassOf<class UGameplayAbility>>& Abilities);
};
#include "AbilityListView.h"
#include "Abilities/GameplayAbility.h"
void UAbilityListView::ConfigureAbilities(const TMap<ECAbilityInputID, TSubclassOf<class UGameplayAbility>>& Abilities)
{
//OnEntryWidgetGenerated().AddUObject()
for (const TPair<ECAbilityInputID, TSubclassOf<UGameplayAbility>>& AbilityPair : Abilities)
{
AddItem(AbilityPair.Value.GetDefaultObject());
}
}
GameplayWidget
中添加技能列表
// 技能列表
UPROPERTY(meta=(BindWidget))
TObjectPtr<UAbilityListView> AbilityListView;
void UGameplayWidget::ConfigureAbilities(const TMap<ECAbilityInputID, TSubclassOf<UGameplayAbility>>& Abilities)
{
AbilityListView->ConfigureAbilities(Abilities);
}
然后还不能用说缺东西
让技能图标继承IUserObjectListEntry
接口
UCLASS()
class CRUNCH_API UAbilityGauge : public UUserWidget, public IUserObjectListEntry
{
GENERATED_BODY()
public:
virtual void NativeOnListItemObjectSet(UObject* ListItemObject) override;
};
void UAbilityGauge::NativeOnListItemObjectSet(UObject* ListItemObject)
{
IUserObjectListEntry::NativeOnListItemObjectSet(ListItemObject);
}
就可以在UI中设置该技能图标类了,下面的数字可以控制显示的数目
调整为水平方向,间距也可以调整
创建数据表
// 技能控件数据结构,用于配置技能UI显示内容
USTRUCT(BlueprintType)
struct FAbilityWidgetData : public FTableRowBase
{
GENERATED_BODY()
// 技能类
UPROPERTY(EditAnywhere, BlueprintReadWrite)
TSubclassOf<class UGameplayAbility> AbilityClass;
// 技能名称
UPROPERTY(EditAnywhere, BlueprintReadWrite)
FName AbilityName;
// 技能图标
UPROPERTY(EditAnywhere, BlueprintReadWrite)
TSoftObjectPtr<UTexture2D> Icon;
// 技能描述
UPROPERTY(EditAnywhere, BlueprintReadWrite)
FText Description;
};
补全技能列表AbilityListView
// 幻雨喜欢小猫咪
#pragma once
#include "CoreMinimal.h"
#include "Components/ListView.h"
#include "GAS/Core/CGameplayAbilityTypes.h"
#include "UI/Gameplay/Abilities/AbilityGauge.h"
#include "AbilityListView.generated.h"
/**
*
*/
UCLASS()
class CRUNCH_API UAbilityListView : public UListView
{
GENERATED_BODY()
public:
// 配置能力表
void ConfigureAbilities(const TMap<ECAbilityInputID, TSubclassOf<class UGameplayAbility>>& Abilities);
private:
UPROPERTY(EditAnywhere, Category = "Data")
TObjectPtr<UDataTable> AbilityDataTable;
// 技能生成绑定
void AbilityGaugeGenerated(UUserWidget& Widget);
// 查找指定技能的UI数据
const FAbilityWidgetData* FindWidgetDataForAbility(const TSubclassOf<UGameplayAbility>& AbilityClass) const;
};
// 幻雨喜欢小猫咪
#include "AbilityListView.h"
#include "Abilities/GameplayAbility.h"
void UAbilityListView::ConfigureAbilities(const TMap<ECAbilityInputID, TSubclassOf<class UGameplayAbility>>& Abilities)
{
OnEntryWidgetGenerated().AddUObject(this, &UAbilityListView::AbilityGaugeGenerated);
// 添加技能
for (const TPair<ECAbilityInputID, TSubclassOf<UGameplayAbility>>& AbilityPair : Abilities)
{
AddItem(AbilityPair.Value.GetDefaultObject());
}
}
void UAbilityListView::AbilityGaugeGenerated(UUserWidget& Widget)
{
UAbilityGauge* AbilityGauge = Cast<UAbilityGauge>(&Widget);
if (AbilityGauge)
{
AbilityGauge->ConfigureWithWidgetData(FindWidgetDataForAbility(AbilityGauge->GetListItem<UGameplayAbility>()->GetClass()));
}
}
const FAbilityWidgetData* UAbilityListView::FindWidgetDataForAbility(
const TSubclassOf<UGameplayAbility>& AbilityClass) const
{
if (!AbilityDataTable) return nullptr;
for (auto& AbilityWidgetDataPair : AbilityDataTable->GetRowMap())
{
const FAbilityWidgetData* WidgetData = AbilityDataTable->FindRow<FAbilityWidgetData>(AbilityWidgetDataPair.Key, "");
if (WidgetData && WidgetData->AbilityClass == AbilityClass)
{
return WidgetData;
}
}
return nullptr;
}
在技能图标中添加配置函数以及要设置的材质对应的图标名称
// 用数据配置控件显示
void ConfigureWithWidgetData(const FAbilityWidgetData* WidgetData);
private:
// 图标材质参数名
UPROPERTY(EditDefaultsOnly, Category = "Visual")
FName IconMaterialParamName = "Icon";
void UAbilityGauge::ConfigureWithWidgetData(const FAbilityWidgetData* WidgetData)
{
if (Icon && WidgetData)
{
// 设置图片
Icon->GetDynamicMaterial()->SetTextureParameterValue(IconMaterialParamName, WidgetData->Icon.LoadSynchronous());
}
}
把数据表添加进去
获取蓝耗以及冷却
在CAbilitySystemStatics
函数类中添加获取技能冷却和技能消耗的函数
UCLASS()
class UCAbilitySystemStatics : public UBlueprintFunctionLibrary
{
GENERATED_BODY()
public:
static FGameplayTag GetBasicAttackAbilityTag();
// 获取技能冷却
static float GetStaticCooldownDurationForAbility(const UGameplayAbility* Ability);
// 获取技能消耗
static float GetStaticCostForAbility(const UGameplayAbility* Ability);
};
float UCAbilitySystemStatics::GetStaticCooldownDurationForAbility(const UGameplayAbility* Ability)
{
if (!Ability) return 0.f;
// 获取冷却效果
const UGameplayEffect* CoolDownEffect = Ability->GetCooldownGameplayEffect();
if (!CoolDownEffect) return 0.f;
float CooldownDuration = 0.f;
// 调用GetStaticMagnitudeIfPossible方法从冷却效果中获取静态持续时间值
CoolDownEffect->DurationMagnitude.GetStaticMagnitudeIfPossible(1, CooldownDuration);
return CooldownDuration;
}
float UCAbilitySystemStatics::GetStaticCostForAbility(const UGameplayAbility* Ability)
{
if (!Ability) return 0.f;
// 获取消耗效果
const UGameplayEffect* CostEffect = Ability->GetCostGameplayEffect();
if (!CostEffect || CostEffect->Modifiers.Num() == 0) return 0.f;
float Cost = 0.f;
CostEffect->Modifiers[0].ModifierMagnitude.GetStaticMagnitudeIfPossible(1, Cost);
// 取正值
return FMath::Abs(Cost);
}
到技能图标AbilityGauge
中设置一下cd和消耗
public:
// 控件构建时调用
virtual void NativeConstruct() override;
private:
// 技能类默认对象
UPROPERTY()
TObjectPtr<UGameplayAbility> AbilityCDO;
void UAbilityGauge::NativeConstruct()
{
Super::NativeConstruct();
// 隐藏冷却计时器
CooldownCounterText->SetVisibility(ESlateVisibility::Hidden);
}
void UAbilityGauge::NativeOnListItemObjectSet(UObject* ListItemObject)
{
IUserObjectListEntry::NativeOnListItemObjectSet(ListItemObject);
AbilityCDO = Cast<UGameplayAbility>(ListItemObject);
// 获取冷却和消耗
float CoolDownDuration = UCAbilitySystemStatics::GetStaticCooldownDurationForAbility(AbilityCDO);
float Cost = UCAbilitySystemStatics::GetStaticCostForAbility(AbilityCDO);
// 设置冷却和消耗
CooldownDurationText->SetText(FText::AsNumber(CoolDownDuration));
CostText->SetText(FText::AsNumber(Cost));
}
运行一下就能显示蓝耗以及cd了(为啥灰的,因为我偷懒了)
让冷却实现倒数计时
private:
// 冷却倒数计时的间隔
UPROPERTY(EditDefaultsOnly, Category = "Cooldown")
float CooldownUpdateInterval = 0.1f;
// 技能释放时回调
void AbilityCommitted(UGameplayAbility* Ability);
// 启动冷却计时
void StartCooldown(float CooldownTimeRemaining, float CooldownDuration);
// 缓存的冷却总时长
float CachedCooldownDuration;
// 缓存的冷却剩余时间
float CachedCooldownTimeRemaining;
// 冷却完成定时器
FTimerHandle CooldownTimerHandle;
// 冷却刷新定时器
FTimerHandle CooldownTimerUpdateHandle;
// 数字格式化选项(整数)
FNumberFormattingOptions WholeNumberFormattingOptions;
// 数字格式化选项(一位小数)
FNumberFormattingOptions TwoDigitNumberFormattingOptions;
// 冷却完成回调
void CooldownFinished();
// 冷却刷新回调
void UpdateCooldown();
void UAbilityGauge::NativeConstruct()
{
Super::NativeConstruct();
// 隐藏冷却计时器
CooldownCounterText->SetVisibility(ESlateVisibility::Hidden);
UAbilitySystemComponent* OwnerASC = UAbilitySystemBlueprintLibrary::GetAbilitySystemComponent(GetOwningPlayerPawn());
if (OwnerASC)
{
// 监听技能释放
OwnerASC->AbilityCommittedCallbacks.AddUObject(this, &UAbilityGauge::AbilityCommitted);
}
WholeNumberFormattingOptions.MaximumFractionalDigits = 0;
TwoDigitNumberFormattingOptions.MaximumFractionalDigits = 2;
}
void UAbilityGauge::AbilityCommitted(UGameplayAbility* Ability)
{
// 判断释放的技能是否为该图标的技能
if (Ability->GetClass()->GetDefaultObject() == AbilityCDO)
{
// 获取技能冷却剩余时长
float CooldownTimeRemaining = 0.f;
// 获取技能冷却总时长
float CooldownDuration = 0.f;
// 返回当前激活的冷却剩余时间(秒)及该冷却的原始持续时间
Ability->GetCooldownTimeRemainingAndDuration(Ability->GetCurrentAbilitySpecHandle(), Ability->GetCurrentActorInfo(), CooldownTimeRemaining, CooldownDuration);
// 启动UI技能冷却
StartCooldown(CooldownTimeRemaining, CooldownDuration);
}
}
void UAbilityGauge::StartCooldown(float CooldownTimeRemaining, float CooldownDuration)
{
// 设置冷却时间
CooldownDurationText->SetText(FText::AsNumber(CooldownDuration));
// 将倒数计时设置为可视
CooldownDurationText->SetVisibility(ESlateVisibility::Visible);
// 缓存冷却总时长
CachedCooldownDuration = CooldownDuration;
// 缓存冷却剩余时间
CachedCooldownTimeRemaining = CooldownTimeRemaining;
// 冷却结束监听
GetWorld()->GetTimerManager().SetTimer(CooldownTimerHandle, this, &UAbilityGauge::CooldownFinished,CachedCooldownTimeRemaining);
// 启动倒数计时
GetWorld()->GetTimerManager().SetTimer(CooldownTimerUpdateHandle, this, &UAbilityGauge::UpdateCooldown, CooldownUpdateInterval, true, 0.f);
}
void UAbilityGauge::CooldownFinished()
{
CachedCooldownDuration = CachedCooldownTimeRemaining = 0.f;
// 冷却结束隐藏倒计时文本
CooldownCounterText->SetVisibility(ESlateVisibility::Hidden);
// 关闭倒数计时定时器
GetWorld()->GetTimerManager().ClearTimer(CooldownTimerUpdateHandle);
}
void UAbilityGauge::UpdateCooldown()
{
// 更新剩余时间
CachedCooldownTimeRemaining -= CooldownUpdateInterval;
// 剩余时间大于1就显示一位数
FNumberFormattingOptions* FormattingOptions = CachedCooldownTimeRemaining > 1 ? &WholeNumberFormattingOptions : &TwoDigitNumberFormattingOptions;
CooldownCounterText->SetText(FText::AsNumber(CachedCooldownTimeRemaining, FormattingOptions));
}
获取到倒数计时的显示
用扫描雷达做冷却倒数材质
技能图标中添加
// 冷却百分比材质参数名
UPROPERTY(EditDefaultsOnly, Category = "Visual")
FName CooldownPercentParamName = "Percent";
void UAbilityGauge::CooldownFinished()
{
CachedCooldownDuration = CachedCooldownTimeRemaining = 0.f;
// 冷却结束隐藏倒计时文本
CooldownCounterText->SetVisibility(ESlateVisibility::Hidden);
// 关闭倒数计时定时器
GetWorld()->GetTimerManager().ClearTimer(CooldownTimerUpdateHandle);
Icon->GetDynamicMaterial()->SetScalarParameterValue(CooldownPercentParamName, 1.f);
}
void UAbilityGauge::UpdateCooldown()
{
// 更新剩余时间
CachedCooldownTimeRemaining -= CooldownUpdateInterval;
// 剩余时间大于1就显示一位数
FNumberFormattingOptions* FormattingOptions = CachedCooldownTimeRemaining > 1 ? &WholeNumberFormattingOptions : &TwoDigitNumberFormattingOptions;
Icon->GetDynamicMaterial()->SetScalarParameterValue(CooldownPercentParamName, 1.0f - CachedCooldownTimeRemaining / CachedCooldownDuration);
CooldownCounterText->SetText(FText::AsNumber(CachedCooldownTimeRemaining, FormattingOptions));
}
技能图标代码
// 幻雨喜欢小猫咪
#pragma once
#include "CoreMinimal.h"
#include "Blueprint/IUserObjectListEntry.h"
#include "Blueprint/UserWidget.h"
#include "Components/Image.h"
#include "Components/TextBlock.h"
#include "AbilityGauge.generated.h"
// 技能控件数据结构,用于配置技能UI显示内容
USTRUCT(BlueprintType)
struct FAbilityWidgetData : public FTableRowBase
{
GENERATED_BODY()
// 技能类
UPROPERTY(EditAnywhere, BlueprintReadWrite)
TSubclassOf<class UGameplayAbility> AbilityClass;
// 技能名称
UPROPERTY(EditAnywhere, BlueprintReadWrite)
FName AbilityName;
// 技能图标
UPROPERTY(EditAnywhere, BlueprintReadWrite)
TSoftObjectPtr<UTexture2D> Icon;
// 技能描述
UPROPERTY(EditAnywhere, BlueprintReadWrite)
FText Description;
};
/**
* 技能槽UI控件,负责显示技能图标、冷却、等级、消耗等信息
* 支持技能升级、冷却计时、能否释放等状态的动态刷新
*/
UCLASS()
class CRUNCH_API UAbilityGauge : public UUserWidget, public IUserObjectListEntry
{
GENERATED_BODY()
public:
// 控件构建时调用
virtual void NativeConstruct() override;
// 列表项对象设置时调用
virtual void NativeOnListItemObjectSet(UObject* ListItemObject) override;
// 用数据配置控件显示
void ConfigureWithWidgetData(const FAbilityWidgetData* WidgetData);
private:
// 冷却倒数计时的间隔
UPROPERTY(EditDefaultsOnly, Category = "Cooldown")
float CooldownUpdateInterval = 0.1f;
// 图标材质参数名
UPROPERTY(EditDefaultsOnly, Category = "Visual")
FName IconMaterialParamName = "Icon";
// 冷却百分比材质参数名
UPROPERTY(EditDefaultsOnly, Category = "Visual")
FName CooldownPercentParamName = "Percent";
// 技能图标
UPROPERTY(meta = (BindWidget))
TObjectPtr<UImage> Icon;
// 冷却计时文本控件
UPROPERTY(meta=(BindWidget))
TObjectPtr<UTextBlock> CooldownCounterText;
// 冷却总时长文本控件
UPROPERTY(meta=(BindWidget))
TObjectPtr<UTextBlock> CooldownDurationText;
// 技能消耗文本控件
UPROPERTY(meta=(BindWidget))
TObjectPtr<UTextBlock> CostText;
// 技能类默认对象
UPROPERTY()
TObjectPtr<UGameplayAbility> AbilityCDO;
// 技能释放时回调
void AbilityCommitted(UGameplayAbility* Ability);
// 启动冷却计时
void StartCooldown(float CooldownTimeRemaining, float CooldownDuration);
// 缓存的冷却总时长
float CachedCooldownDuration;
// 缓存的冷却剩余时间
float CachedCooldownTimeRemaining;
// 冷却完成定时器
FTimerHandle CooldownTimerHandle;
// 冷却刷新定时器
FTimerHandle CooldownTimerUpdateHandle;
// 数字格式化选项(整数)
FNumberFormattingOptions WholeNumberFormattingOptions;
// 数字格式化选项(一位小数)
FNumberFormattingOptions TwoDigitNumberFormattingOptions;
// 冷却完成回调,隐藏冷却文本并重置进度条
void CooldownFinished();
// 冷却刷新回调,更新冷却文本和进度条
void UpdateCooldown();
};
// 幻雨喜欢小猫咪
#include "UI/Gameplay/Abilities/AbilityGauge.h"
#include "AbilitySystemBlueprintLibrary.h"
#include "AbilitySystemComponent.h"
#include "Components/Image.h"
#include "GAS/Core/CAbilitySystemStatics.h"
#include "Abilities/GameplayAbility.h"
void UAbilityGauge::NativeConstruct()
{
Super::NativeConstruct();
// 隐藏冷却计时器
CooldownCounterText->SetVisibility(ESlateVisibility::Hidden);
UAbilitySystemComponent* OwnerASC = UAbilitySystemBlueprintLibrary::GetAbilitySystemComponent(GetOwningPlayerPawn());
if (OwnerASC)
{
// 监听技能释放
OwnerASC->AbilityCommittedCallbacks.AddUObject(this, &UAbilityGauge::AbilityCommitted);
}
WholeNumberFormattingOptions.MaximumFractionalDigits = 0;
TwoDigitNumberFormattingOptions.MaximumFractionalDigits = 2;
}
void UAbilityGauge::NativeOnListItemObjectSet(UObject* ListItemObject)
{
IUserObjectListEntry::NativeOnListItemObjectSet(ListItemObject);
AbilityCDO = Cast<UGameplayAbility>(ListItemObject);
// 获取冷却和消耗
float CoolDownDuration = UCAbilitySystemStatics::GetStaticCooldownDurationForAbility(AbilityCDO);
float Cost = UCAbilitySystemStatics::GetStaticCostForAbility(AbilityCDO);
// 设置冷却和消耗
CooldownDurationText->SetText(FText::AsNumber(CoolDownDuration));
CostText->SetText(FText::AsNumber(Cost));
}
void UAbilityGauge::ConfigureWithWidgetData(const FAbilityWidgetData* WidgetData)
{
if (Icon && WidgetData)
{
// 设置图片
Icon->GetDynamicMaterial()->SetTextureParameterValue(IconMaterialParamName, WidgetData->Icon.LoadSynchronous());
}
}
void UAbilityGauge::AbilityCommitted(UGameplayAbility* Ability)
{
// 判断释放的技能是否为该图标的技能
if (Ability->GetClass()->GetDefaultObject() == AbilityCDO)
{
// 获取技能冷却剩余时长
float CooldownTimeRemaining = 0.f;
// 获取技能冷却总时长
float CooldownDuration = 0.f;
// 返回当前激活的冷却剩余时间(秒)及该冷却的原始持续时间
Ability->GetCooldownTimeRemainingAndDuration(Ability->GetCurrentAbilitySpecHandle(), Ability->GetCurrentActorInfo(), CooldownTimeRemaining, CooldownDuration);
// 启动UI技能冷却
StartCooldown(CooldownTimeRemaining, CooldownDuration);
}
}
void UAbilityGauge::StartCooldown(float CooldownTimeRemaining, float CooldownDuration)
{
// 设置冷却时间
// CooldownDurationText->SetText(FText::AsNumber(CooldownDuration));
CooldownCounterText->SetText(FText::AsNumber(CooldownDuration));
// 缓存冷却总时长
CachedCooldownDuration = CooldownDuration;
// 缓存冷却剩余时间
CachedCooldownTimeRemaining = CooldownTimeRemaining;
// 将倒数计时设置为可视
CooldownCounterText->SetVisibility(ESlateVisibility::Visible);
// 冷却结束监听
GetWorld()->GetTimerManager().SetTimer(CooldownTimerHandle, this, &UAbilityGauge::CooldownFinished,CachedCooldownTimeRemaining);
// 启动倒数计时
GetWorld()->GetTimerManager().SetTimer(CooldownTimerUpdateHandle, this, &UAbilityGauge::UpdateCooldown, CooldownUpdateInterval, true, 0.f);
}
void UAbilityGauge::CooldownFinished()
{
CachedCooldownDuration = CachedCooldownTimeRemaining = 0.f;
// 冷却结束隐藏倒计时文本
CooldownCounterText->SetVisibility(ESlateVisibility::Hidden);
// 关闭倒数计时定时器
GetWorld()->GetTimerManager().ClearTimer(CooldownTimerUpdateHandle);
Icon->GetDynamicMaterial()->SetScalarParameterValue(CooldownPercentParamName, 1.f);
}
void UAbilityGauge::UpdateCooldown()
{
// 更新剩余时间
CachedCooldownTimeRemaining -= CooldownUpdateInterval;
// 剩余时间大于1就显示一位数
FNumberFormattingOptions* FormattingOptions = CachedCooldownTimeRemaining > 1 ? &WholeNumberFormattingOptions : &TwoDigitNumberFormattingOptions;
Icon->GetDynamicMaterial()->SetScalarParameterValue(CooldownPercentParamName, 1.0f - CachedCooldownTimeRemaining / CachedCooldownDuration);
CooldownCounterText->SetText(FText::AsNumber(CachedCooldownTimeRemaining, FormattingOptions));
}
技能列表代码
// 幻雨喜欢小猫咪
#pragma once
#include "CoreMinimal.h"
#include "Components/ListView.h"
#include "GAS/Core/CGameplayAbilityTypes.h"
#include "UI/Gameplay/Abilities/AbilityGauge.h"
#include "AbilityListView.generated.h"
/**
*
*/
UCLASS()
class CRUNCH_API UAbilityListView : public UListView
{
GENERATED_BODY()
public:
// 配置能力表
void ConfigureAbilities(const TMap<ECAbilityInputID, TSubclassOf<class UGameplayAbility>>& Abilities);
private:
UPROPERTY(EditAnywhere, Category = "Data")
TObjectPtr<UDataTable> AbilityDataTable;
// 技能生成绑定
void AbilityGaugeGenerated(UUserWidget& Widget);
// 查找指定技能的UI数据
const FAbilityWidgetData* FindWidgetDataForAbility(const TSubclassOf<UGameplayAbility>& AbilityClass) const;
};
// 幻雨喜欢小猫咪
#include "AbilityListView.h"
#include "Abilities/GameplayAbility.h"
void UAbilityListView::ConfigureAbilities(const TMap<ECAbilityInputID, TSubclassOf<class UGameplayAbility>>& Abilities)
{
// 绑定技能生成事件
OnEntryWidgetGenerated().AddUObject(this, &UAbilityListView::AbilityGaugeGenerated);
// 添加技能
for (const TPair<ECAbilityInputID, TSubclassOf<UGameplayAbility>>& AbilityPair : Abilities)
{
AddItem(AbilityPair.Value.GetDefaultObject());
}
}
void UAbilityListView::AbilityGaugeGenerated(UUserWidget& Widget)
{
// 将控件转换为UAbilityGauge类型
UAbilityGauge* AbilityGauge = Cast<UAbilityGauge>(&Widget);
if (AbilityGauge)
{
// 查找并配置技能计量器的数据
AbilityGauge->ConfigureWithWidgetData(FindWidgetDataForAbility(AbilityGauge->GetListItem<UGameplayAbility>()->GetClass()));
}
}
const FAbilityWidgetData* UAbilityListView::FindWidgetDataForAbility(
const TSubclassOf<UGameplayAbility>& AbilityClass) const
{
// 如果数据表为空则直接返回nullptr
if (!AbilityDataTable) return nullptr;
// 遍历数据表的所有行
for (auto& AbilityWidgetDataPair : AbilityDataTable->GetRowMap())
{
// 查找当前行的数据
const FAbilityWidgetData* WidgetData = AbilityDataTable->FindRow<FAbilityWidgetData>(AbilityWidgetDataPair.Key, "");
// 如果找到数据且技能类匹配则返回
if (WidgetData && WidgetData->AbilityClass == AbilityClass)
{
return WidgetData;
}
}
// 未找到匹配的数据
return nullptr;
}