16. UE5 RPG获取GE应用的回调,并根据Tag设置数据显示到窗口

在上一篇介绍了对标签如何在项目中设置,这一篇先讲解一下如何在GE里面使用GameplayTag标签。
之前我在第十一章节中 11. UE5 RPG使用GameplayEffect修改角色属性(二)介绍了一些GE的属性,在UE 5.3版本中,修改的配置方式,需要在组件里面设置需要的组件
下图为与标签相关的组件
在这里插入图片描述

查看当前actor拥有的标签

首先,我们在一个用于持续性时间的GE上面添加一个标签,比如我在一个回血的GE上面添加了一个Health的标签
在这里插入图片描述
然后运行游戏,按~建打开debug
在这里插入图片描述
左上角会显示当前actor拥有的标签,当前actor是没有任何标签的
在这里插入图片描述
在应用了对应的GE后,会发现角色身上多出了对应的标签,在GE效果消失后,对应的标签也被剔除。后面的括号内的数值代表当前添加的数量,它也可以被堆叠。注意,通过GE堆叠的方式是无法让标签产生堆叠的。如果设置不堆叠,每个是单独的GE,那么会出现标签堆叠的效果。
在这里插入图片描述

ASC使用委托监听GE

接下来我们要实现GE被应用时,使用委托触发回调,进行其它处理
翻看ASC.h的源码,会发现有相应的委托代码,委托返回ASC,GE的实例,GE的引用三个参数
在这里插入图片描述
接着往下看,会发现基于这个委托宏,创建了多个委托属性,有添加GE给自身触发的,有添加给目标触发的,有持续时间的GE添加给自身触发的,还有周期性触发的GE的委托等等。
在这里插入图片描述

鼠标悬停到属性上面也能够查看到对应的返回
在这里插入图片描述
接下来,我们要实现的就是绑定委托,在给自身添加GE时,打印GE附加的Asset Tag

在AbilitySystemComponentBase 技能组件基类里面,我们添加一个AbilityActorInfoSet()函数,这个函数用于初始化委托的注册。
然后添加一个委托触发的回调函数EffectApplied()这个函数将在GE被添加的时候触发。

// 版权归暮志未晚所有。#pragma once#include "CoreMinimal.h"
#include "AbilitySystemComponent.h"
#include "AbilitySystemComponentBase.generated.h"/*** 技能系统组件*/
UCLASS()
class AURA_API UAbilitySystemComponentBase : public UAbilitySystemComponent
{GENERATED_BODY()public:void AbilityActorInfoSet();protected:void EffectApplied(UAbilitySystemComponent* AbilitySystemComponent, const FGameplayEffectSpec& EffectSpec, FActiveGameplayEffectHandle ActiveGameplayEffectHandle);
};

在cpp中,我们将对其进行实现,AbilityActorInfoSet()中先绑定了一个GE添加到自身的委托,事件触发时将调用EffectApplied()函数,EffectApplied()函数内,现在将获取到GE身上的AssetTags,并通过遍历的形式打印出来。

// 版权归暮志未晚所有。#include "AbilitySystem/AbilitySystemComponentBase.h"void UAbilitySystemComponentBase::AbilityActorInfoSet()
{OnGameplayEffectAppliedDelegateToSelf.AddUObject(this, &UAbilitySystemComponentBase::EffectApplied);
}void UAbilitySystemComponentBase::EffectApplied(UAbilitySystemComponent* AbilitySystemComponent,const FGameplayEffectSpec& EffectSpec, FActiveGameplayEffectHandle ActiveGameplayEffectHandle)
{// GEngine->AddOnScreenDebugMessage(1, 8.f, FColor::Blue, FString("Effect Applied!"));FGameplayTagContainer TagContainer;EffectSpec.GetAllAssetTags(TagContainer);for(const FGameplayTag& Tag : TagContainer){//TODO: 将tag广播给Widget Controllerconst FString Msg = FString::Printf(TEXT("GE Tag: %s"), *Tag.ToString()); //获取Asset TagGEngine->AddOnScreenDebugMessage(-1, 8.f, FColor::Cyan, Msg); //打印到屏幕上 -1 不会被覆盖}
}

ASC的基础类添加了,我们还需要对其进行调用,事件委托的绑定需要在ASC初始化完成后调用。

在所有的角色基类上面我们添加一个virtual void InitAbilityActorInfo();这个函数用于初始化ASC的委托注册,下面为初始化的代码

Cast<UAbilitySystemComponentBase>(AbilitySystemComponent)->AbilityActorInfoSet();

在基类上,我们不去做实现,实现在英雄类和敌人类里面去实现。

在英雄类里面,在原来的基础上,初始化ASC后进行调用

void AHeroCharacter::PossessedBy(AController* NewController)
{Super::PossessedBy(NewController);//初始化ASC的OwnerActor和AvatarActorInitAbilityActorInfo();//设置OwnerActor的ControllerSetOwner(NewController);
}void AHeroCharacter::OnRep_PlayerState()
{Super::OnRep_PlayerState();//初始化ASC的OwnerActor和AvatarActorInitAbilityActorInfo();
}void AHeroCharacter::InitAbilityActorInfo()
{APlayerStateBase* PlayerStateBase = GetPlayerState<APlayerStateBase>();check(PlayerStateBase); //检测是否有效,无限会暂停游戏//从playerState获取ASC和ASAbilitySystemComponent = PlayerStateBase->GetAbilitySystemComponent();AttributeSet = PlayerStateBase->GetAttributeSet();//初始化ASCAbilitySystemComponent->InitAbilityActorInfo(PlayerStateBase, this);//触发Actor的技能信息设置回调Cast<UAbilitySystemComponentBase>(AbilitySystemComponent)->AbilityActorInfoSet(); //获取PCif(APlayerControllerBase* PlayerControllerBase = Cast<APlayerControllerBase>(GetController())){if(AMyHUD* HUD = Cast<AMyHUD>(PlayerControllerBase->GetHUD())){HUD->InitOverlay(PlayerControllerBase, PlayerStateBase, AbilitySystemComponent, AttributeSet);}}}

在敌人类里面,初始化委托方式一致

void AEnemyBase::BeginPlay()
{Super::BeginPlay();InitAbilityActorInfo();
}void AEnemyBase::InitAbilityActorInfo()
{AbilitySystemComponent->InitAbilityActorInfo(this, this);Cast<UAbilitySystemComponentBase>(AbilitySystemComponent)->AbilityActorInfoSet();
}

在初始化完成后,我们在UE里面的GE添加AssetTagsGameplayEffectComponent,并且添加对应的Tags,测试应用时是否有打印。
在这里插入图片描述

使用委托将ASC和Widget Controller绑定

上面我们实现了获取添加GE时的回调,并能够打印对应GE上面添加的Tags,接下来,我们要实现ASC和Widget Controller之间的沟通,在GE添加时,在WidgetController里面也能够获取到Broadcast广播,并触发对应的回调。

ASC.h在之前的基础上,添加一个委托宏设置FEffectAssetTags,然后定义一个属性EffectAssetTags用于后续的广播。

// 版权归暮志未晚所有。#pragma once#include "CoreMinimal.h"
#include "AbilitySystemComponent.h"
#include "AbilitySystemComponentBase.generated.h"DECLARE_MULTICAST_DELEGATE_OneParam(FEffectAssetTags, const FGameplayTagContainer& /* AssetTags */)/*** 技能系统组件*/
UCLASS()
class AURA_API UAbilitySystemComponentBase : public UAbilitySystemComponent
{GENERATED_BODY()public:void AbilityActorInfoSet();FEffectAssetTags EffectAssetTags;protected:void EffectApplied(UAbilitySystemComponent* AbilitySystemComponent, const FGameplayEffectSpec& EffectSpec, FActiveGameplayEffectHandle ActiveGameplayEffectHandle);
};

在cpp里,EffectApplied是添加GE后的事件回调,之前我们是直接在这里打印的tags,现在我们修改成获取到TagContainer后,将TagContainer进行委托广播出去。

// 版权归暮志未晚所有。#include "AbilitySystem/AbilitySystemComponentBase.h"void UAbilitySystemComponentBase::AbilityActorInfoSet()
{OnGameplayEffectAppliedDelegateToSelf.AddUObject(this, &UAbilitySystemComponentBase::EffectApplied);
}void UAbilitySystemComponentBase::EffectApplied(UAbilitySystemComponent* AbilitySystemComponent,const FGameplayEffectSpec& EffectSpec, FActiveGameplayEffectHandle ActiveGameplayEffectHandle)
{// GEngine->AddOnScreenDebugMessage(1, 8.f, FColor::Blue, FString("Effect Applied!"));FGameplayTagContainer TagContainer;EffectSpec.GetAllAssetTags(TagContainer);EffectAssetTags.Broadcast(TagContainer);
}

之前我们制作的,先初始化ASC完成以后,然后通过HUD类对Widget用户控件初始化,然后再对Widget Controller初始化的。所以,在初始化Widget Controller时,ASC是初始化完成的。
我们在Widget Controller绑定事件委托里面,添加对ASC的委托EffectAssetTags进行监听即可。

以下是用户控件使用的Widget Controller的初始化委托监听的函数,前面的是之前监听AS属性值变化的代码,后面我们通过AddLambda添加了一个匿名函数,用于监听EffectAssetTags,并在里面进行测试打印。

void UOverlayWidgetController::BindCallbacksToDependencies()
{const UAttributeSetBase* AttributeSetBase = CastChecked<UAttributeSetBase>(AttributeSet);AbilitySystemComponent->GetGameplayAttributeValueChangeDelegate(AttributeSetBase->GetHealthAttribute()).AddUObject(this, &UOverlayWidgetController::HealthChanged);AbilitySystemComponent->GetGameplayAttributeValueChangeDelegate(AttributeSetBase->GetMaxHealthAttribute()).AddUObject(this, &UOverlayWidgetController::MaxHealthChanged);AbilitySystemComponent->GetGameplayAttributeValueChangeDelegate(AttributeSetBase->GetManaAttribute()).AddUObject(this, &UOverlayWidgetController::ManaChanged);AbilitySystemComponent->GetGameplayAttributeValueChangeDelegate(AttributeSetBase->GetMaxManaAttribute()).AddUObject(this, &UOverlayWidgetController::MaxManaChanged);//AddLambda 绑定匿名函数Cast<UAbilitySystemComponentBase>(AbilitySystemComponent)->EffectAssetTags.AddLambda([](const FGameplayTagContainer& AssetTags){for(const FGameplayTag& Tag : AssetTags){//将tag广播给Widget Controllerconst FString Msg = FString::Printf(TEXT("GE Tag in Widget Controller: %s"), *Tag.ToString()); //获取Asset TagGEngine->AddOnScreenDebugMessage(-1, 8.f, FColor::Cyan, Msg); //打印到屏幕上 -1 不会被覆盖}});
}

接着运行代码,发现左上角打印了对应的tags,代表代码无误。
在这里插入图片描述

创建标签消息委托

上面我们实现了可以在添加GE的时候,打印GE身上的Tag,接下来,将实现在Widget里面通过委托获取GE的应用标签。

首先,在WidgetController里面,创建一个结构体,这个结构体可以被蓝图使用。
结构体内主要存储一些数据,用于在ui上面展示使用,所以,我们需要GE的信息Tag,提示文本信息,使用的Widget控件,以及显示的图片都存储到结构体内。

USTRUCT(BlueprintType)
struct FUIWidgetRow : public FTableRowBase
{GENERATED_BODY();UPROPERTY(EditAnywhere, BlueprintReadOnly)FGameplayTag MessageTag = FGameplayTag();UPROPERTY(EditAnywhere, BlueprintReadOnly)FText Message = FText();UPROPERTY(EditAnywhere, BlueprintReadOnly)TSubclassOf<class UMyUserWidget> MessageWidget;UPROPERTY(EditAnywhere, BlueprintReadOnly)UTexture2D* Image = nullptr;
};

编译后,创建一个数据表格,类就选择我们创建的结构体。
在这里插入图片描述
接下来,我们要实现数据使用的内容,首先创建信息Tag,在GameplayTag标签管理器里面,添加信息标签。
在这里插入图片描述
到现在我们还没有创建Widget显示控件,先把别的内容填上
在这里插入图片描述
接下来在WidgetController上面增加一个配置项,用于配置数据

	//EditDefaultsOnly 说明此属性可以通过属性窗口编辑,但只能在原型上进行。UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="Widget Data")TObjectPtr<UDataTable> MessageWidgetDataTable;

将刚才创建的数据表格设置
在这里插入图片描述
接着创建一个可以通过Tag在数据表格中寻找对应的数据的函数,为了兼容不同的数据表格,这里我们使用不确定的T类型,在调用时指定返回类型。

	//根据传入的表格和Tag返回查找到的数据,表格类型不确定,所以使用T来表示,在使用此函数时,需要指定对应类型template<typename T>T* GetDataTableRowByTag(UDataTable* DataTable, const FGameplayTag& Tag);
template <typename T>
T* UOverlayWidgetController::GetDataTableRowByTag(UDataTable* DataTable, const FGameplayTag& Tag)
{T* Row = DataTable->FindRow<T>(Tag.GetTagName(), TEXT(""));return Row;
}

在之前我们实现的匿名函数里面,首先添加的GE内是否包含Message的Tag,如果包含,则广播出去。

	//AddLambda 绑定匿名函数Cast<UAbilitySystemComponentBase>(AbilitySystemComponent)->EffectAssetTags.AddLambda([this](const FGameplayTagContainer& AssetTags) //中括号添加this是为了保证内部能够获取类的对象{for(const FGameplayTag& Tag : AssetTags){//对标签进行检测,如果不是信息标签,将无法进行广播FGameplayTag MessageTag = FGameplayTag::RequestGameplayTag(FName("Message"));// "A.1".MatchesTag("A") will return True, "A".MatchesTag("A.1") will return Falseif(Tag.MatchesTag(MessageTag)){FUIWidgetRow* Row = GetDataTableRowByTag<FUIWidgetRow>(MessageWidgetDataTable, Tag);MessageWidgetRowDelegate.Broadcast(*Row); //前面加*取消指针引用}}});

代码逻辑基本实现到这,然后我们需要在药瓶的GE里面添加Tag
在这里插入图片描述
然后做一个测试,在Widget中,先将Controller类型转换为OverlayWidgetController
在这里插入图片描述
接着监听数据返回,打印信息
在这里插入图片描述
数据能够打印,证明准确无误
在这里插入图片描述

创建信息Widget

结构体内,我们还有一项没有实现,那就是Widget组件,接下来,我们将实现这个组件。
首先创建一个用户控件,基类就使用我们之前实现的基类
在这里插入图片描述
在Widget里面,创建一个显示图片和文本的对象组件。
在这里插入图片描述
如果以水平框作为最外层,会被父节点拉伸,我们可以使用一个覆层包裹一下。
在这里插入图片描述

图表里面增加一个设置图片和文本的蓝图函数。
在这里插入图片描述
创建完成,我们可以将数据表格的数据填充上去对于的Widget
在这里插入图片描述

接下来,我们就可以修改Overlay的debug的蓝图,不用再打印文本,而是直接添加widget到视口。
下图为修改后的蓝图节点,我们使用数据创建一个widget,并设置显示在屏幕中间,
在这里插入图片描述
接下来,我们给widget制作了一个新的动画,并添加到了设置函数上面,在设置完成属性后,播放动画
在这里插入图片描述
播放动画后面的执行,是直接执行的,不是在动画播放完成执行,所以,我们需要制作一个事件,在延迟动画的时间后,销毁掉,并在销毁回调中测试
在这里插入图片描述
在测试捡起药瓶后,检查动画是否播放完成,回调是否触发,这样不会造成内存溢出。
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/748308.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

药店在线客服机器人的设计与开发

摘要 随着信息技术的快速发展和人工智能领域的不断进步&#xff0c;药店在线客服机器人已经成为现代药店服务模式中不可或缺的一部分&#xff0c;这种机器人技术通过模拟人类客服代表&#xff0c;能够提供24/7的咨询服务&#xff0c;从而大幅提高服务效率和顾客满意度&#xff…

集合系列(二) -List接口详解

一、List简介 List 的数据结构就是一个序列&#xff0c;存储内容时直接在内存中开辟一块连续的空间&#xff0c;然后将空间地址与索引对应。 以下是List集合简易架构图 由图中的继承关系&#xff0c;可以知道&#xff0c;ArrayList、LinkedList、Vector、Stack都是List的四个…

软件设计和体系结构

软件设计和体系结构 一、引言 软件 定义&#xff1a;一系列按照特定顺序组织的计算机数据、指令的集合 特点&#xff1a; 软件不是生产制造&#xff0c;是设计开发软件不会磨损和老化软件需要根据实际情况进行定制开发 软件设计的基本原则 抽象方法 过程抽象&#xff1a;是指…

进程和ELF文件

程序的二进制格式&#xff1a; 关联知识&#xff1a;GCC编译原理与使用-CSDN博客 linux二进制程序的严格格式&#xff1a;ELF&#xff08;Executeable and Linkable format&#xff09; 一 预处理&#xff0c;编译&#xff0c;汇编得到的.o文件&#xff0c;就是ELF的第一种类…

Altium Designer快速入门及项目实战教程之层次原理图PCB设计(七)

一、简介 层次PCB设计是电子工程领域中一项至关重要的任务&#xff0c;它涉及到电路板的各个层面的功能分配和布局规划。这一设计过程的关键在于如何合理安排每一层的功能和布局&#xff0c;以确保电路板的性能达到最佳状态&#xff0c;并同时保证其可靠性。 首先&#xff0c…

数据结构 第3章:栈与队列

文章目录 1. 栈1.1 栈的基本概念1.2 栈的基本操作1.3 栈的顺序存储实现1.4 栈的链式存储实现 2. 队列2.1 队列的基本概念2.2 队列的基本操作2.3. 队列的顺序存储实现2.4 队列的链式存储实现2.5 双端队列 3. 栈与队列的应用3.1 栈在括号匹配中的应用3.2 栈在表达式求值中的应用3…

6.JavaWebJDBC连接池、JDBCTemplate

目录 导语&#xff1a; 一、JDBC连接池概述 常见JDBC连接池&#xff1a; JDBC连接池的优点 二、JDBCTemplate介绍 JDBCTemplate的核心组件 JDBCTemplate的使用方法 JDBCTemplate的优点 结语&#xff1a; ​​​​​​​ 导语&#xff1a; 在Java数据库编程中&#xf…

macOS Monterey 12.7.4 (21H1123) Boot ISO 原版可引导镜像下载

macOS Monterey 12.7.4 (21H1123) Boot ISO 原版可引导镜像下载 3 月 8 日凌晨&#xff0c;macOS Sonoma 14.4 发布&#xff0c;同时带来了 macOS Ventru 13.6.5 和 macOS Monterey 12.7.4 安全更新。 本站下载的 macOS 软件包&#xff0c;既可以拖拽到 Applications&#xf…

Hive-技术补充-初识ANTLR

一、背景 要清晰的理解一条Hql是如何编译成MapReduce任务的&#xff0c;就必须要学习ANTLR。下面是ANTLR的官方网址&#xff0c;下面让我们一起来跟着官网学习吧&#xff0c;在学习的过程中我参考了《antlr4权威指南》&#xff0c;你也可以读下这本书&#xff0c;一定会对你有…

在idea中配置tomcat服务器,部署一个项目(下载教程加链接)

第一步&#xff1a;把Tomcat下载好 ww​​​​​​​Apache Tomcat - Welcome! 链接如上&#xff1a;进去后在左边找到Tomcat8点击进去后 找到图下内容 第二步&#xff1a; 打开这个文件点击bin进去 会出现一个黑色框框&#xff0c;也就是服务器 完成后就可以在浏览器输入…

【C++】实现红黑树

目录 一、认识红黑树1.1 概念1.2 定义 二、实现红黑树2.1 插入2.2 与AVL树对比 一、认识红黑树 1.1 概念 红黑树是一个二叉搜索树&#xff0c;与AVL树相比&#xff0c;红黑树不再使用平衡因子来控制树的左右子树高度差&#xff0c;而是用颜色来控制平衡&#xff0c;颜色为红色…

Keil笔记(缘更)

Keil 一、使用Keil时可能会出现的问题1.Project框不见了2.添加文件时找不到3.交换文件位置4.main.c测试报1 warning 二、STLINK点灯操作1.配置寄存器进行点灯2.使用库函数进行点灯 3.GPIO1.LED闪烁 一、使用Keil时可能会出现的问题 1.Project框不见了 view->Project Windo…

Naive Ui Admin:企业级中后台项目开箱即用框架/让你少写一些代码

欢迎加入我们的前端组件学习交流群&#xff0c;可添加群主微信&#xff0c;审核通过后入群。 Naive Ui Admin&#xff1a;企业级中后台项目开箱即用框架/让你少写一些代码 在数字化时代&#xff0c;中后台系统对于企业的运营至关重要。然而&#xff0c;构建这样的系统往往需要…

Unity URP 如何写基础的曲面细分着色器

左边是默认Cube在网格模式下经过曲面细分的结果&#xff0c;右边是原状态。 曲面细分着色器在顶点着色器、几何着色器之后&#xff0c;像素着色器之前。 它的作用时根据配置信息生成额外的顶点以切割原本的面片。 关于这部分有一个详细的英文教程&#xff0c;感兴趣可以看一…

AtomoVideo:AIGC赋能下的电商视频动效生成

✍&#x1f3fb; 本文作者&#xff1a;凌潼、依竹、桅桔、逾溪 1. 概述 当今电商领域&#xff0c;内容营销的形式正日趋多样化&#xff0c;视频内容以其生动鲜明的视觉体验和迅捷高效的信息传播能力&#xff0c;为商家创造了新的机遇。消费者对视频内容的偏好驱动了视频创意供给…

Redis部署方式(三)主从模式

在前面单机版的基础上&#xff0c;41为主&#xff0c;30为从。 一、主从搭建 1、主Redis安装 41机器redis主要配置 requirepass redis#!_41 bind 0.0.0.0 port 6379 daemonize yes 2、从redis安装 30机器redis主要配置 requirepass redis#!_30 bind 0.0.0.0 port 6380 da…

python 如何使用 NLPchina 开源sql插件,提供代码

分享一段使用python&#xff0c;通过使用发送post请求的方式&#xff0c;来从es集群中获取数据。不用使用 elasticsearh&#xff0c;仅需要导入request和json包即可。 开源sql插件官方 文档 GitHub - NLPchina/elasticsearch-sql: Use SQL to query Elasticsearch 示例代码 调…

JavaScript中的事件模型(详细案例代码)

文章目录 一、事件与事件流二、事件模型原始事件模型特性 标准事件模型特性 IE事件模型 一、事件与事件流 javascript中的事件&#xff0c;可以理解就是在HTML文档或者浏览器中发生的一种交互操作&#xff0c;使得网页具备互动性&#xff0c; 常见的有加载事件、鼠标事件、自定…

js实现扫描线填色算法使用canvas展示

算法原理 扫描线填色算法的基本思想是&#xff1a;用水平扫描线从上到下扫描由点线段构成的多段构成的多边形。每根扫描线与多边形各边产生一系列交点。将这些交点按照x坐标进行分类&#xff0c;将分类后的交点成对取出&#xff0c;作为两个端点&#xff0c;以所填的色彩画水平…

文章解读与仿真程序复现思路——电网技术EI\CSCD\北大核心《适应分布式资源渗透率提高的配电网网元规划方法》

本专栏栏目提供文章与程序复现思路&#xff0c;具体已有的论文与论文源程序可翻阅本博主免费的专栏栏目《论文与完整程序》 论文与完整源程序_电网论文源程序的博客-CSDN博客https://blog.csdn.net/liang674027206/category_12531414.html 电网论文源程序-CSDN博客电网论文源…