1、创建头部血条
添加一个cpp类继承UserWidget
,命名为OverHeadStatsGauge
添加血条和蓝条,以及绑定回调用的函数
// 幻雨喜欢小猫咪
#pragma once
#include "CoreMinimal.h"
#include "ValueGauge.h"
#include "Blueprint/UserWidget.h"
#include "OverHeadStatsGauge.generated.h"
/**
*
*/
UCLASS()
class UOverHeadStatsGauge : public UUserWidget
{
GENERATED_BODY()
public:
void ConfigureWithASC(class UAbilitySystemComponent* AbilitySystemComponent);
private:
UPROPERTY(meta = (BindWidget))
TObjectPtr<UValueGauge> HealthBar;
UPROPERTY(meta = (BindWidget))
TObjectPtr<UValueGauge> ManaBar;
};
// 幻雨喜欢小猫咪
#include "UI/Gameplay/OverHeadStatsGauge.h"
#include "GAS/CAttributeSet.h"
void UOverHeadStatsGauge::ConfigureWithASC(UAbilitySystemComponent* AbilitySystemComponent)
{
if (AbilitySystemComponent)
{
HealthBar->SetAndBoundToGameplayAttribute(AbilitySystemComponent, UCAttributeSet::GetHealthAttribute(), UCAttributeSet::GetMaxHealthAttribute());
ManaBar->SetAndBoundToGameplayAttribute(AbilitySystemComponent, UCAttributeSet::GetManaAttribute(), UCAttributeSet::GetMaxManaAttribute());
}
}
随后在引擎继承该类创建蓝图WBP_OverHeadStatsGauge
2、装载到角色上
到CCharacter
中添加UI组件以及初始化函数,像血条这种东西我们就不用在自己头上亮血条了,还需要一个判断角色是否由本地玩家控制
// 客户端中初始化
void ClientSideInit();
/*放这里*/
// 判断该角色是否由本地玩家控制
bool IsLocallyControlledByPlayer() const;
#pragma region UI
private:
// 头顶UI
UPROPERTY(VisibleDefaultsOnly, Category = "UI")
TObjectPtr<UWidgetComponent> OverHeadWidgetComponent;
void ConfigureOverHeadStatusWidget();
#pragma endregion
构造函数中添加如下,并对ConfigureOverHeadStatusWidget
函数进行实现,在开始游戏的时候调用该函数:
ACCharacter::ACCharacter()
{
OverHeadWidgetComponent = CreateDefaultSubobject<UWidgetComponent>(TEXT("OverHeadWidgetComponent"));
OverHeadWidgetComponent->SetupAttachment(GetRootComponent());
}
bool ACCharacter::IsLocallyControlledByPlayer() const
{
return GetController() && GetController()->IsLocalPlayerController();
}
void ACCharacter::BeginPlay()
{
Super::BeginPlay();
ConfigureOverHeadStatusWidget();
}
void ACCharacter::ConfigureOverHeadStatusWidget()
{
// 检查头顶UI组件是否存在,如果不存在则直接返回
if (!OverHeadWidgetComponent)
{
return;
}
// 如果角色由本地玩家控制
if (IsLocallyControlledByPlayer())
{
// 隐藏头顶UI组件
OverHeadWidgetComponent->SetHiddenInGame(true);
return;
}
// 将头顶UI组件的用户控件对象转换为UOverHeadStatsGauge类型
UOverHeadStatsGauge* OverheadStatsGuage = Cast<UOverHeadStatsGauge>(OverHeadWidgetComponent->GetUserWidgetObject());
if (OverheadStatsGuage)
{
// 使用能力系统组件配置头顶统计量表
OverheadStatsGuage->ConfigureWithASC(GetAbilitySystemComponent());
// 显示头顶UI组件
OverHeadWidgetComponent->SetHiddenInGame(false);
}
}
随后在蓝图中设置,于此就能实现头部血条的制作
3、血条的些许优化
#pragma region UI
private:
// 头顶UI
UPROPERTY(VisibleDefaultsOnly, Category = "UI")
TObjectPtr<UWidgetComponent> OverHeadWidgetComponent;
void ConfigureOverHeadStatusWidget();
/**
* @brief 头顶状态条更新间隔时间(秒)\n
* 控制头顶UI显示/隐藏检测的刷新频率,单位为秒。\n
* 可在编辑器中调整,默认值为1秒。
*/
UPROPERTY(EditDefaultsOnly, Category = "UI")
float HeadStatGaugeVisibilityCheckUpdateGap = 1.f;
/**
* @brief 头顶状态条可见性检测的距离平方阈值\n
* 当玩家与角色之间的距离平方小于该值时,显示头顶UI;\n
* 可在编辑器中调整,默认值为10,000,000。
*/
UPROPERTY(EditDefaultsOnly, Category = "UI")
float HeadStatGaugeVisibilityRangeSquared = 10000000.f;
// 用于控制头顶状态条可见性更新的定时器句柄
FTimerHandle HeadStatGaugeVisibilityUpdateTimerHandle;
/**
* @brief 更新头顶状态条可见性\n
* 根据玩家与角色之间的距离判断是否启用头顶UI组件的显示。\n
* 该方法通过定时器周期性调用。
*/
void UpdateHeadGaugeVisibility();
#pragma endregion
void ACCharacter::ConfigureOverHeadStatusWidget()
{
// 检查头顶UI组件是否存在,如果不存在则直接返回
if (!OverHeadWidgetComponent)
{
return;
}
// 如果角色由本地玩家控制
if (IsLocallyControlledByPlayer())
{
// 隐藏头顶UI组件
OverHeadWidgetComponent->SetHiddenInGame(true);
return;
}
// 将头顶UI组件的用户控件对象转换为UOverHeadStatsGauge类型
UOverHeadStatsGauge* OverheadStatsGuage = Cast<UOverHeadStatsGauge>(OverHeadWidgetComponent->GetUserWidgetObject());
if (OverheadStatsGuage)
{
// 使用能力系统组件配置头顶统计量表
OverheadStatsGuage->ConfigureWithASC(GetAbilitySystemComponent());
// 显示头顶UI组件
OverHeadWidgetComponent->SetHiddenInGame(false);
/*******************************下面启动定时器*********************************/
// 清除之前的定时器,防止重复调用
GetWorldTimerManager().ClearTimer(HeadStatGaugeVisibilityUpdateTimerHandle);
// 设置新的定时器,周期性调用 UpdateHeadGaugeVisibility 方法
// 用于持续检测角色与玩家之间的距离并更新头顶UI可见性状态
GetWorldTimerManager().SetTimer(
HeadStatGaugeVisibilityUpdateTimerHandle, // 定时器句柄
this, // 绑定对象
&ACCharacter::UpdateHeadGaugeVisibility, // 每一定时间调用的函数
HeadStatGaugeVisibilityCheckUpdateGap, // 更新间隔时间(秒)
true // 是否循环调用true为循环,false为单次
);
}
}
// 定时器调用的更新函数的实现
void ACCharacter::UpdateHeadGaugeVisibility()
{
// 获取本地玩家的Pawn角色,用于计算与当前角色的距离
APawn* LocalPlayerPawn = UGameplayStatics::GetPlayerPawn(this, 0);
if (LocalPlayerPawn)
{
// 计算当前角色与本地玩家之间的平方距离
float DistSquared = FVector::DistSquared(GetActorLocation(), LocalPlayerPawn->GetActorLocation());
// 如果距离超过设定的可见范围,则隐藏头顶状态条组件
OverHeadWidgetComponent->SetHiddenInGame(DistSquared > HeadStatGaugeVisibilityRangeSquared);
}
}
超出一定距离后ui界面消失