UE5多人MOBA+GAS 26、为角色添加每秒回血回蓝(番外:添加到UI上)

文章目录


添加生命值和蓝量的状态标签

添加新的标签

cpp 复制代码
	CRUNCH_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(Stats_Health_Full)
	CRUNCH_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(Stats_Health_Empty)
	CRUNCH_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(Stats_Mana_Full)
	CRUNCH_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(Stats_Mana_Empty)
cpp 复制代码
	UE_DEFINE_GAMEPLAY_TAG_COMMENT(Stats_Health_Full, "Stats.Health.Full", "生命值满")
	UE_DEFINE_GAMEPLAY_TAG_COMMENT(Stats_Mana_Full, "Stats.Mana.Full", "法术值满")
	UE_DEFINE_GAMEPLAY_TAG_COMMENT(Stats_Health_Empty, "Stats.Health.Empty", "生命值空")
	UE_DEFINE_GAMEPLAY_TAG_COMMENT(Stats_Mana_Empty, "Stats.Mana.Empty", "法术值空")

创建无限GE并应用

创建两个GE应用为无限,添加一个组件,死掉和满状态的时候不激活该GE

把两个GE添加到角色中去

监听添加和去除标签

对ASC中监听生命值和法力值的变化进行更改对其添加tag和移除tag(不知道有啥用)

cpp 复制代码
void UCAbilitySystemComponent::HealthUpdated(const FOnAttributeChangeData& ChangeData)
{
	if (!GetOwner() || !GetOwner()->HasAuthority()) return;

	// 获取当前最大生命值
	bool bFound = false;
	float MaxHealth = GetGameplayAttributeValue(UCAttributeSet::GetMaxHealthAttribute(), bFound);
    
	// 如果生命值达到最大值,添加生命值已满标签
	if (bFound && ChangeData.NewValue >= MaxHealth)
	{
		if (!HasMatchingGameplayTag(TGameplayTags::Stats_Health_Full))
		{
			// 仅本地会添加标签
			AddLooseGameplayTag(TGameplayTags::Stats_Health_Full);
		}
	}
	else
	{
		// 移除生命值已满标签
		RemoveLooseGameplayTag(TGameplayTags::Stats_Health_Full);
	}
	if (ChangeData.NewValue <= 0.0f)
	{
		if (!HasMatchingGameplayTag(TGameplayTags::Stats_Health_Empty))
		{
			// 本地添加生命值清零标签
			AddLooseGameplayTag(TGameplayTags::Stats_Health_Empty);
			// 角色死亡
			if (DeathEffect)
			{
				AuthApplyGameplayEffect(DeathEffect);
			}
		}
	}else
	{
		RemoveLooseGameplayTag(TGameplayTags::Stats_Health_Empty);
	}
}

void UCAbilitySystemComponent::ManaUpdated(const FOnAttributeChangeData& ChangeData)
{
	// 仅在拥有者存在且为服务器时执行
	if (!GetOwner() || !GetOwner()->HasAuthority()) return;

	// 获取当前最大魔法值
	bool bFound = false;
	float MaxMana = GetGameplayAttributeValue(UCAttributeSet::GetMaxManaAttribute(), bFound);
    
	// 如果魔法值达到最大值,添加魔法值已满标签
	if (bFound && ChangeData.NewValue >= MaxMana)
	{
		if (!HasMatchingGameplayTag(TGameplayTags::Stats_Mana_Full))
		{
			// 仅本地生效的标签
			AddLooseGameplayTag(TGameplayTags::Stats_Mana_Full);
		}
	}
	else
	{
		// 移除魔法值已满标签
		RemoveLooseGameplayTag(TGameplayTags::Stats_Mana_Full);
	}

	// 处理魔法值为零的情况
	if (ChangeData.NewValue <= 0)
	{
		if (!HasMatchingGameplayTag(TGameplayTags::Stats_Mana_Empty))
		{
			// 添加魔法值清零标签
			AddLooseGameplayTag(TGameplayTags::Stats_Mana_Empty);
		}
	}
	else
	{
		// 移除魔法值清零标签
		RemoveLooseGameplayTag(TGameplayTags::Stats_Mana_Empty);
	}
}

每秒回复配上UI

cpp 复制代码
public:
	// 设置每秒回复值
	void SetRegenValueTextToGameplayAttribute(UAbilitySystemComponent* AbilitySystemComponent,const FGameplayAttribute& Attribute);
	void SetRegenValue(float NewRegenValue);
private:
	void RegenValueChanged(const FOnAttributeChangeData& ChangeData);
	// 每秒回复的数值显示,默认为false,小兵不配这个
	UPROPERTY(EditAnywhere, Category = "Visual")
	bool bRegenValueTextVisible = false;

	// 放置右边显示每秒回复的数值
	UPROPERTY(VisibleAnywhere, meta = (BindWidget))
	TObjectPtr<UTextBlock> RegenValueText;
cpp 复制代码
void UValueGauge::NativePreConstruct()
{
	Super::NativePreConstruct();
	// 设置进度条颜色
	ProgressBar->SetFillColorAndOpacity(BarColor);
	
	ValueText->SetFont(ValueTextFont);
	RegenValueText->SetFont(ValueTextFont);
	
	ValueText->SetVisibility(bValueTextVisible ? ESlateVisibility::Visible : ESlateVisibility::Hidden);
	ProgressBar->SetVisibility(bProgressBarVisible ? ESlateVisibility::Visible : ESlateVisibility::Hidden);
	RegenValueText->SetVisibility(bRegenValueTextVisible ? ESlateVisibility::Visible : ESlateVisibility::Hidden);
}
void UValueGauge::SetRegenValueTextToGameplayAttribute(UAbilitySystemComponent* AbilitySystemComponent,
	const FGameplayAttribute& Attribute)
{
	if (AbilitySystemComponent)
	{
		bool bFound;
		float Value = AbilitySystemComponent->GetGameplayAttributeValue(Attribute, bFound);
		// 如果成功找到对应的属性值,则更新数值指示器的显示
		if (bFound)
		{
			SetRegenValue(Value);
		}
		// 注册属性变化回调,当属性值发生变化时更新数值指示器显示
		AbilitySystemComponent->GetGameplayAttributeValueChangeDelegate(Attribute).AddUObject(this, &UValueGauge::RegenValueChanged);
	}
}

void UValueGauge::SetRegenValue(float NewRegenValue)
{
	// 设置数字格式选项,最大小数位数为0
	const FNumberFormattingOptions FormatOps = FNumberFormattingOptions().SetMaximumFractionalDigits(0);
	// 更新文本显示
	RegenValueText->SetText(
		FText::Format(
			FTextFormat::FromString("{0}/s"),			 // 格式字符串
			FText::AsNumber(NewRegenValue, &FormatOps)      // 当前值
		)
	);
}

void UValueGauge::RegenValueChanged(const FOnAttributeChangeData& ChangeData)
{
	SetRegenValue(ChangeData.NewValue);
}

GameplayWidget中添加绑定

cpp 复制代码
void UGameplayWidget::NativeConstruct()
{
	Super::NativeConstruct();
	OwnerAbilitySystemComponent = UAbilitySystemBlueprintLibrary::GetAbilitySystemComponent(GetOwningPlayerPawn());
	if (OwnerAbilitySystemComponent)
	{
		// 绑定属性回调
		HealthBar->SetAndBoundToGameplayAttribute(OwnerAbilitySystemComponent, UCAttributeSet::GetHealthAttribute(), UCAttributeSet::GetMaxHealthAttribute());
		ManaBar->SetAndBoundToGameplayAttribute(OwnerAbilitySystemComponent, UCAttributeSet::GetManaAttribute(), UCAttributeSet::GetMaxManaAttribute());

		// 绑定每秒回复的属性
		HealthBar->SetRegenValueTextToGameplayAttribute(OwnerAbilitySystemComponent, UCHeroAttributeSet::GetHealthRegenAttribute());
		ManaBar->SetRegenValueTextToGameplayAttribute(OwnerAbilitySystemComponent, UCHeroAttributeSet::GetManaRegenAttribute());
	}
}

构建一下把文本添加进去


相关推荐
一抓掉一大把3 分钟前
秒杀-StackExchangeRedisHelper连接单例
java·开发语言·jvm
升鲜宝供应链及收银系统源代码服务4 分钟前
升鲜宝生鲜配送供应链管理系统--- 《多语言商品查询优化方案(Redis + 翻译表 + 模糊匹配)》
java·数据库·redis·bootstrap·供应链系统·生鲜配送·生鲜配送源代码
青山的青衫13 分钟前
【JavaWeb】Tlias后台管理系统
java·web
蒟蒻的工具人19 分钟前
SSE实时推送订单状态
java·eventsource·sse协议
小蒜学长23 分钟前
springboot基于Java的校园导航微信小程序的设计与实现(代码+数据库+LW)
java·spring boot·后端·微信小程序
王元_SmallA1 小时前
IDEA + Spring Boot 的三种热加载方案
java·后端
小苏兮1 小时前
【把Linux“聊”明白】编译器gcc/g++与调试器gdb/cgdb:从编译原理到高效调试
java·linux·运维·学习·1024程序员节
Java天梯之路1 小时前
04 数据类型转换
java
Acrelhuang1 小时前
小小电能表,如何撬动家庭能源革命?
java·大数据·开发语言·人工智能·物联网
jyd01242 小时前
MongoDB 与 Java 实体类型 LocalTime 时区转换问题解决方案
java·数据库·mongodb