当前位置: 首页 > news >正文

虚幻引擎5 GAS开发俯视角RPG游戏 #5-8:倾听属性变化

摘要:本文展示了一个在UE5中实现属性监听回调的系统设计。首先在WidgetController基类中定义虚函数BindCallbacksToDependencies(),然后在OverlayWidgetController子类中实现该函数,监听生命值和法力值属性的变化。当属性变化时触发对应的回调函数,通过广播机制通知UI更新。属性集初始值在CC_AttributeSet中设置,而回调绑定函数在HUD中初始化WidgetController后调用。最终实现了属性变化时UI自动更新的效果。

1.在类Source/CC_Aura/Public/UI/WidgetController/CC_WidgetController.h里写父函数:

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

2.在子类实现:

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

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

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

void UCC_OverlayWidgetController::BindCallbacksToDependencies()
{if (CC_AttributeSet == nullptr){CC_AttributeSet = Cast<UCC_AttributeSet>(AttributeSet);}//监听属性变化AbilitySystemComponent->GetGameplayAttributeValueChangeDelegate(CC_AttributeSet->GetHealthAttribute()) .AddUObject(this, &UCC_OverlayWidgetController::HealthChanged);AbilitySystemComponent->GetGameplayAttributeValueChangeDelegate(CC_AttributeSet->GetMaxHealthAttribute()) .AddUObject(this, &UCC_OverlayWidgetController::MaxHealthChanged);AbilitySystemComponent->GetGameplayAttributeValueChangeDelegate(CC_AttributeSet->GetManaAttribute()) .AddUObject(this, &UCC_OverlayWidgetController::ManaChanged);AbilitySystemComponent->GetGameplayAttributeValueChangeDelegate(CC_AttributeSet->GetMaxManaAttribute()) .AddUObject(this, &UCC_OverlayWidgetController::MaxManaChanged);
}

回调函数:

void UCC_OverlayWidgetController::HealthChanged(const FOnAttributeChangeData& Data) const
{OnHealthChanged.Broadcast(Data.NewValue);
}void UCC_OverlayWidgetController::MaxHealthChanged(const FOnAttributeChangeData& Data) const
{OnMaxHealthChanged.Broadcast(Data.NewValue);
}void UCC_OverlayWidgetController::ManaChanged(const FOnAttributeChangeData& Data) const
{OnManaChanged.Broadcast(Data.NewValue);
}void UCC_OverlayWidgetController::MaxManaChanged(const FOnAttributeChangeData& Data) const
{OnMaxManaChanged.Broadcast(Data.NewValue);
}

这段代码展示了UE5中GAS(游戏能力系统)的UI属性绑定机制,主要功能是通过委托系统实现属性变化时UI的自动更新。以下是关键点分析:

属性监听机制‌:

  • 使用GetGameplayAttributeValueChangeDelegate获取属性变化的委托
  • 通过AddUObject将成员函数绑定为回调

委托广播实现‌:

  • 定义了多个动态多播委托类型(如FOnHealthChangedSignature
  • 属性变化时通过Broadcast方法通知所有监听者

数据传递方式‌:

  • 使用FOnAttributeChangeData结构体传递新旧属性值
  • 通过NewValue获取更新后的属性数值

控制器架构‌:

  • 属于WidgetController模式
  • 负责连接数据层(AttributeSet)和表现层(Widget)

这种实现方式在RPG游戏中常用于实时更新血条、魔法值等UI元素,通过委托机制实现数据与UI的解耦。

3.将属性集初始值改变,到蓝图里测试:

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

UCC_AttributeSet::UCC_AttributeSet()
{InitHealth(45.f);InitMaxHealth(100.f);InitMana(50.f);InitMaxMana(100.f);
}

4.但,我们到哪里去调用函数BindCallbacksToDependencies()呢?什么时候调用?

答案:

我们在HUD中进行调用

当小部件控制器设置好参数后,就可以绑定监听数据的函数了:

Source/CC_Aura/Private/UI/HUD/CC_HUD.cpp:

效果:

吃药前:

吃药后:

完美!!!!!!!

源代码:

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

// 版权归陈超所有#pragma once#include "CoreMinimal.h"
#include "UI/WidgetController/CC_WidgetController.h"
#include "CC_OverlayWidgetController.generated.h"struct FOnAttributeChangeData;
class UCC_AttributeSet;
//添加动态多播委托
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnHealthChangedSignature, float, NewHealth);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnMaxHealthChangedSignature, float, NewMaxHealth);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnManaChangedSignature, float, NewMana);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnMaxManaChangedSignature, float, NewMaxMana);/*** */
UCLASS(Blueprintable)
class CC_AURA_API UCC_OverlayWidgetController : public UCC_WidgetController
{GENERATED_BODY()
public://广播初始值virtual void BroadcastInitialValues() override;//依赖的绑定回调函数virtual void BindCallbacksToDependencies() override;
protected://动态多播委托UPROPERTY(BlueprintAssignable, Category="GAS|Attributes")FOnHealthChangedSignature OnHealthChanged;UPROPERTY(BlueprintAssignable, Category="GAS|Attributes")FOnMaxHealthChangedSignature OnMaxHealthChanged;UPROPERTY(BlueprintAssignable, Category="GAS|Attributes")FOnManaChangedSignature OnManaChanged;UPROPERTY(BlueprintAssignable, Category="GAS|Attributes")FOnMaxManaChangedSignature OnMaxManaChanged;private:UPROPERTY()TObjectPtr<UCC_AttributeSet> CC_AttributeSet;//属性变化的回调函数void HealthChanged(const FOnAttributeChangeData& Data) const;void MaxHealthChanged(const FOnAttributeChangeData& Data) const;void ManaChanged(const FOnAttributeChangeData& Data) const;void MaxManaChanged(const FOnAttributeChangeData& Data) const;};

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

// 版权归陈超所有#include "UI/WidgetController/CC_OverlayWidgetController.h"#include "AbilitySystem/CC_AttributeSet.h"void UCC_OverlayWidgetController::BroadcastInitialValues()
{if (CC_AttributeSet == nullptr){CC_AttributeSet = Cast<UCC_AttributeSet>(AttributeSet);}//广播属性变化OnHealthChanged.Broadcast(CC_AttributeSet->GetHealth());OnMaxHealthChanged.Broadcast(CC_AttributeSet->GetMaxHealth());OnManaChanged.Broadcast(CC_AttributeSet->GetMana());OnMaxManaChanged.Broadcast(CC_AttributeSet->GetMaxMana());
}void UCC_OverlayWidgetController::BindCallbacksToDependencies()
{if (CC_AttributeSet == nullptr){CC_AttributeSet = Cast<UCC_AttributeSet>(AttributeSet);}//监听属性变化AbilitySystemComponent->GetGameplayAttributeValueChangeDelegate(CC_AttributeSet->GetHealthAttribute()) .AddUObject(this, &UCC_OverlayWidgetController::HealthChanged);AbilitySystemComponent->GetGameplayAttributeValueChangeDelegate(CC_AttributeSet->GetMaxHealthAttribute()) .AddUObject(this, &UCC_OverlayWidgetController::MaxHealthChanged);AbilitySystemComponent->GetGameplayAttributeValueChangeDelegate(CC_AttributeSet->GetManaAttribute()) .AddUObject(this, &UCC_OverlayWidgetController::ManaChanged);AbilitySystemComponent->GetGameplayAttributeValueChangeDelegate(CC_AttributeSet->GetMaxManaAttribute()) .AddUObject(this, &UCC_OverlayWidgetController::MaxManaChanged);
}void UCC_OverlayWidgetController::HealthChanged(const FOnAttributeChangeData& Data) const
{OnHealthChanged.Broadcast(Data.NewValue);
}void UCC_OverlayWidgetController::MaxHealthChanged(const FOnAttributeChangeData& Data) const
{OnMaxHealthChanged.Broadcast(Data.NewValue);
}void UCC_OverlayWidgetController::ManaChanged(const FOnAttributeChangeData& Data) const
{OnManaChanged.Broadcast(Data.NewValue);
}void UCC_OverlayWidgetController::MaxManaChanged(const FOnAttributeChangeData& Data) const
{OnMaxManaChanged.Broadcast(Data.NewValue);
}

Source/CC_Aura/Public/UI/HUD/CC_HUD.h:

// 版权归陈超所有#pragma once#include "CoreMinimal.h"
#include "GameFramework/HUD.h"
#include "CC_HUD.generated.h"class UAttributeSet;
class UAbilitySystemComponent;
struct FWidgetControllerParams;
class UCC_OverlayWidgetController;
class UCC_UserWidget;
/*** */
UCLASS()
class CC_AURA_API ACC_HUD : public AHUD
{GENERATED_BODY()public:UPROPERTY(EditAnywhere, BlueprintReadWrite)TObjectPtr<UCC_UserWidget> OverlayWidget;		//覆盖层小部件UCC_OverlayWidgetController* GetOverlayWidgetController(/*const FWidgetControllerParams& FWCParams*/);void InitOverlay(APlayerController* PC, APlayerState* PS, UAbilitySystemComponent* ASC, UAttributeSet* AS);private:UPROPERTY(EditAnywhere)TSubclassOf<UCC_UserWidget> OverlayWidgetClass;		//覆盖层小部件类UPROPERTY()TObjectPtr<UCC_OverlayWidgetController> OverlayWidgetController;	//覆盖层小部件控制器//覆盖层小部件的类、子类UPROPERTY(EditAnywhere)TSubclassOf<UCC_OverlayWidgetController> OverlayWidgetControllerClass;
};

Source/CC_Aura/Private/UI/HUD/CC_HUD.cpp:

// 版权归陈超所有#include "UI/HUD/CC_HUD.h"
#include "UI/Widget/CC_UserWidget.h"
#include "UI/WidgetController/CC_OverlayWidgetController.h"UCC_OverlayWidgetController* ACC_HUD::GetOverlayWidgetController(/*const FWidgetControllerParams& FWCParams*/)
{if (OverlayWidgetController == nullptr)	{//创建覆盖层小部件控制器OverlayWidgetController = NewObject<UCC_OverlayWidgetController>(this, OverlayWidgetControllerClass);// OverlayWidgetController->SetWidgetControllerParams(FWCParams);}return OverlayWidgetController;
}void ACC_HUD::InitOverlay(APlayerController* PC, APlayerState* PS, UAbilitySystemComponent* ASC, UAttributeSet* AS)
{checkf(OverlayWidgetClass,TEXT("OverlayWidgetClass没有设定!"));checkf(OverlayWidgetControllerClass,TEXT("OverlayWidgetControllerClass没有设定!"));//1.创建小部件UUserWidget* Widget = CreateWidget<UUserWidget>(GetWorld(), OverlayWidgetClass);OverlayWidget = Cast<UCC_UserWidget>(Widget);//2.创建小部件控制器const FWidgetControllerParams WidgetControllerParams = FWidgetControllerParams(PC, PS, ASC, AS);//获取覆盖层小部件控制器指针OverlayWidgetController = GetOverlayWidgetController();//将参数赋值给小部件控制器OverlayWidgetController->SetWidgetControllerParams(WidgetControllerParams);//小部件控制器监听属性变化,触发回调OverlayWidgetController->BindCallbacksToDependencies();//3.将小部件控制器添加到小部件OverlayWidget->AddWidgetController(OverlayWidgetController);//4.小部件控制器广播初始值OverlayWidgetController->BroadcastInitialValues();//将覆盖层小部件打印到屏幕OverlayWidget->AddToViewport();
}

http://www.dtcms.com/a/270882.html

相关文章:

  • 【视频观看系统】- 需求分析
  • 在overleaf中使用bibtex格式引用文献
  • 算法核心知识复习:排序算法对比 + 递归与递推深度解析(根据GESP四级题目总结)
  • Java SE 实现简单的图书管理系统(完善菜单操作)
  • Linux入门篇学习——Linux 编写第一个自己的命令
  • 深度学习 必然用到的 微积分知识
  • 基于pytorch.nn模块实现softmax回归模型
  • 我是如何实现在线客服系统的极致稳定性与安全性的
  • NumPy-广播机制深入理解
  • HashMap的put、get方法详解(附源码)
  • 冷冻电镜重构的GPU加速破局:从Relion到CryoSPARC的并行重构算法
  • 【前端】异步任务风控验证与轮询机制技术方案(通用笔记版)
  • 在Centos系统上如何有效删除文件和目录的指令汇总
  • 【C++ 】第二章——类(Class)学习笔记
  • SpringGateway网关增加https证书验证
  • 基于YOLO的足球检测Web应用:从训练到部署的完整实战
  • 《心灵沟通小平台,创新发展大未来》
  • brainstorm MEG处理流程
  • 2024 睿抗编程技能赛——省赛真题解析(含C++源码)
  • 图像匹配方向最新论文--CoMatch: Covisibility-Aware Transformer for Subpixel Matching
  • 【QT】文件、多线程、网络相关内容
  • 【基础算法】贪心 (四) :区间问题
  • spring-data-jpa + Alibaba Druid多数据源案例
  • (5)机器学习小白入门 YOLOv:数据需求与图像不足应对策略
  • OpenCV图片操作100例:从入门到精通指南(4)
  • [C#/.NET] 内网开发中如何使用 System.Text.Json 实现 JSON 解析(无需 NuGet)
  • 树莓派vsftpd文件传输服务器的配置方法
  • Java 大视界 -- 基于 Java 的大数据分布式计算在生物信息学蛋白质 - 蛋白质相互作用预测中的应用(340)
  • 【算法深练】DFS题型拆解:沿着路径“深挖到底”、递归深入、回溯回探的算法解题思路
  • 【数据分析】多数据集网络分析:探索健康与退休研究中的变量关系