93. UE5 GAS RPG 应用负面效果表现

news2024/9/21 19:42:50

在上一篇文章里,我们实现了添加负面效果GE,并且在添加GE时,也会给角色应用一个负面效果标签作为标识。在这一篇里,我们将通过负面效果标签标识,应用角色身上展现对应的负面效果的表现。
我们将在这篇文章里添加一个自定义的Niagara组件,来实现对应的负面效果表现,并通过观察角色身上是否应用的对应的标签,来激活和取消激活组件。

解决应用标签的bug

首先我们解决之前编写的通过代码设置GE标签的方法。
和之前的相比,有两处问题,第一处就是不应该直接获取,而是直接创建一个新的FInheritedTagContainer。
第二处是在添加的地方需要设置到Added对象上,对应UE里设置GE。

UTargetTagsGameplayEffectComponent& TargetTagsGameplayEffectComponent = Effect->AddComponent<UTargetTagsGameplayEffectComponent>();
FInheritedTagContainer InheritableOwnedTagsContainer; //创建组件所需的标签容器
InheritableOwnedTagsContainer.Added.AddTag(DeBuffType); //添加标签
TargetTagsGameplayEffectComponent.SetAndApplyTargetTagChanges(InheritableOwnedTagsContainer); //应用并更新

创建自定义的Niagara组件类

为了能够自定义负面效果表现的自动开关功能,我们需要自己扩展Niagara类,在里面增加内容。
我们基于NiagaraComponent创建一个派生类
在这里插入图片描述
设定好相关名称和目录
在这里插入图片描述
在派生类里,我们添加构造函数,设置标识当前对应的负面效果的标签,以及对应标签变动回调以及角色死亡回调。

UCLASS()
class RPG_API UDeBuffNiagaraComponent : public UNiagaraComponent
{
	GENERATED_BODY()

public:

	UDeBuffNiagaraComponent();
	
	UPROPERTY(EditDefaultsOnly)
	FGameplayTag DeBuffTag; //用来标识粒子系统的标签

protected:
	virtual void BeginPlay() override; //覆写开始运行
	void DeBuffTagChanged(const FGameplayTag CallbackTag, int32 NewCount); //当前的负面标签变动回调

	UFUNCTION()
	void OnOwnerDeath(AActor* DeadActor); //在角色死亡时的回调
};

在构造函数中,我们将自动激活关闭

UDeBuffNiagaraComponent::UDeBuffNiagaraComponent()
{
	bAutoActivate = false; //关闭自动激活
}

在事件开始执行时,我们绑定对应的回调,用来检测角色的变动,并在变动时触发回调

void UDeBuffNiagaraComponent::BeginPlay()
{
	Super::BeginPlay();

	ICombatInterface* CombatInterface = Cast<ICombatInterface>(GetOwner()); //获取到战斗接口
	//通过函数库获取角色身上的ASC
	if(UAbilitySystemComponent* ASC = UAbilitySystemBlueprintLibrary::GetAbilitySystemComponent(GetOwner()))
	{
		//监听负面标签变动回调
		ASC->RegisterGameplayTagEvent(DeBuffTag, EGameplayTagEventType::NewOrRemoved).AddUObject(this, &UDeBuffNiagaraComponent::DeBuffTagChanged);
	}
	else if(CombatInterface) //如果绑定时,ASC未初始化成功,则监听ASC创建完成委托,完成对负面标签的监听
	{
		//AddWeakLambda 这种绑定方式的主要好处是,当绑定的对象被销毁时,委托不会保持对象的引用,从而避免悬空指针问题和内存泄漏。
		CombatInterface->GetOnASCRegisteredDelegate().AddWeakLambda(this,[this](UAbilitySystemComponent* InASC)
		{
			//监听负面标签变动回调
			InASC->RegisterGameplayTagEvent(DeBuffTag, EGameplayTagEventType::NewOrRemoved).AddUObject(this, &UDeBuffNiagaraComponent::DeBuffTagChanged);
		});
	}
	//绑定死亡后销毁
	if(CombatInterface)
	{
		CombatInterface->GetOnDeathDelegate().AddDynamic(this, &UDeBuffNiagaraComponent::OnOwnerDeath);
	}
}

监听负面效果标签的回调里,我们可以获取角色身上对应标签的个数,如果不为0,则激活粒子

void UDeBuffNiagaraComponent::DeBuffTagChanged(const FGameplayTag CallbackTag, int32 NewCount)
{
	if(NewCount > 0)
	{
		Activate(); //绑定的负面标签大于0,激活特效
	}
	else
	{
		Deactivate(); //没有对应标签,关闭激活
	}
}

在触发死亡回调时,关闭激活

void UDeBuffNiagaraComponent::OnOwnerDeath(AActor* DeadActor)
{
	Deactivate();
}

添加对应委托

在自定义Niagara组件里,我们需要两个委托来监听角色身上的负面标签变动以及角色是否死亡
在战斗接口类里,我们增加两个委托,可以通过其进行绑定
Dynamic的区别在于能不能绑定蓝图,非Dynamic的无法绑定,Dynamic的需要通过UE反射绑定,也可以直接蓝图获取绑定。

DECLARE_MULTICAST_DELEGATE_OneParam(FOnASCRegistered, UAbilitySystemComponent*); //Actor初始化ASC完成后委托
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnDeath, AActor*, DeadActor); //Actor死亡后的委托

然后我们在类里增加两个获取函数,可以获取对应的委托,这里我们需要返回引用

	virtual FOnASCRegistered& GetOnASCRegisteredDelegate() = 0; //获取ASC注册成功后的委托
	virtual FOnDeath& GetOnDeathDelegate() = 0; //获取死亡委托

接着,我们在角色基类里增加两个对应的委托

	FOnASCRegistered OnASCRegistered; //ASC注册成功委托
	FOnDeath OnDeath; //角色死亡后触发的死亡委托

覆写两个函数

	virtual FOnASCRegistered& GetOnASCRegisteredDelegate() override; //获取ASC注册成功委托
	virtual FOnDeath& GetOnDeathDelegate() override; //角色死亡委托

对其实现一下,返回对应的委托

FOnASCRegistered& ARPGCharacter::GetOnASCRegisteredDelegate()
{
	return OnASCRegistered;
}

FOnDeath& ARPGCharacter::GetOnDeathDelegate()
{
	return OnDeath;
}

触发委托

现在我们创建完成了对应的委托,还需要在合适的位置对其进行广播
首先是ASC创建完成后的广播,我选择在InitAbilityActorInfo函数里,创建完成ASC后广播

void ARPGEnemy::InitAbilityActorInfo()
{
	AbilitySystemComponent->InitAbilityActorInfo(this, this);
	Cast<URPGAbilitySystemComponent>(AbilitySystemComponent)->AbilityActorInfoSet();

	//通过GE初始角色的属性
	if(HasAuthority())
	{
		InitializeDefaultAttributes();
	}

	//调用ASC广播
	OnASCRegistered.Broadcast(AbilitySystemComponent);
}

角色的函数内容不同,在函数执行完时,也完成了广播

void ARPGHero::InitAbilityActorInfo()
{
	ARPGPlayerState* PlayerStateBase = GetPlayerState<ARPGPlayerState>();
	check(PlayerStateBase); //检测是否有效,无限会暂停游戏
	//从playerState获取ASC和AS
	AbilitySystemComponent = PlayerStateBase->GetAbilitySystemComponent();
	AttributeSet = PlayerStateBase->GetAttributeSet();
	//初始化ASC
	AbilitySystemComponent->InitAbilityActorInfo(PlayerStateBase, this);
	//触发Actor的技能信息设置回调
	Cast<URPGAbilitySystemComponent>(AbilitySystemComponent)->AbilityActorInfoSet(); 

	//获取PC
	if(ARPGPlayerController* PlayerControllerBase = Cast<ARPGPlayerController>(GetController()))
	{
		if(ARPGHUD* HUD = Cast<ARPGHUD>(PlayerControllerBase->GetHUD()))
		{
			HUD->InitOverlay(PlayerControllerBase, PlayerStateBase, AbilitySystemComponent, AttributeSet);
		}
	}

	//通过GE初始角色的属性
	InitializeDefaultAttributes();

	//调用ASC广播
	OnASCRegistered.Broadcast(AbilitySystemComponent);
}

然后就是角色的死亡委托广播,我们之前创建了一个多播函数,在角色死亡后,每个游戏端都会触发此函数

void ARPGCharacter::MulticastHandleDeath_Implementation()
{
	//播放死亡音效
	UGameplayStatics::PlaySoundAtLocation(this, DeathSound, GetActorLocation());
	
	//开启武器物理效果
	Weapon->SetSimulatePhysics(true); //开启模拟物理效果
	Weapon->SetEnableGravity(true); //开启重力效果
	Weapon->SetCollisionEnabled(ECollisionEnabled::PhysicsOnly); //开启物理碰撞通道

	//开启角色物理效果
	GetMesh()->SetSimulatePhysics(true); //开启模拟物理效果
	GetMesh()->SetEnableGravity(true); //开启重力效果
	GetMesh()->SetCollisionEnabled(ECollisionEnabled::PhysicsOnly); //开启物理碰撞通道
	GetMesh()->SetCollisionResponseToChannel(ECC_WorldStatic, ECR_Block); //开启角色与静态物体产生碰撞

	//关闭角色碰撞体碰撞通道,避免其对武器和角色模拟物理效果产生影响
	GetCapsuleComponent()->SetCollisionEnabled(ECollisionEnabled::NoCollision);

	//设置角色溶解
	Dissolve();

	//设置死亡状态
	bDead = true;
	
	//触发死亡委托
	OnDeath.Broadcast(this);
}

在蓝图编辑

接着,我们在角色积累增加一个Niagara组件,设置火的负面效果

	UPROPERTY(VisibleAnywhere) //火焰负面效果表现组件
	TObjectPtr<UDeBuffNiagaraComponent> BurnDeBuffComponent;

在构造函数里初始化,并设置好对应的负面标签

	//初始化火焰负面效果组件
	BurnDeBuffComponent = CreateDefaultSubobject<UDeBuffNiagaraComponent>("BurnDeBuffComponent");
	BurnDeBuffComponent->SetupAttachment(GetRootComponent());
	BurnDeBuffComponent->DeBuffTag = FRPGGameplayTags::Get().DeBuff_Burn; //设置匹配的负面标签

编译打开UE,可以看到,里面增加了对应的组件
在这里插入图片描述
我们可以在组件上设置使用的Niagara资产
在这里插入图片描述
还可以修改对应的DeBuff标签
在这里插入图片描述
实现完成后,我们需要进行测试,测试的主要内容是

  1. 在激活负面效果时,是否能够正确激活Niagara
  2. 在负面效果结束时,标签是否能够在角色身上正确清除,Niagara是否能够自动结束
  3. 在激活负面效果时,角色死亡是否能够自动停止激活等待销毁。
    如果都没有问题,基本上效果实现完毕。

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

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

相关文章

第一个React程序

虽然跟着网上的视频&#xff0c;但是都是几年前的教学视频了&#xff0c;于是就在视频的引导下&#xff0c;自己使用vite脚手架建立一个React项目。 首先来到vite官网&#xff1a; 和当时建立vue项目一样&#xff0c;使用该命令创建&#xff0c;只是后面选择框架时选择react&a…

《机器学习》 基于SVD的矩阵分解 推导、案例实现

目录 一、SVD奇异值分解 1、什么是SVD 2、SVD的应用 1&#xff09;数据降维 2&#xff09;推荐算法 3&#xff09;自然语言处理 3、核心 1&#xff09;什么是酉矩阵 2&#xff09;什么是对角矩阵 4、分解过程 二、推导 1、如何求解这三个矩阵 1&#xff09;已知&#xf…

10款好用的电脑监控软件推荐丨2024年干货整理,赶紧码住!

选择合适的电脑监控软件可以帮助企业和个人更好地管理和保护其计算机资源。以下是10款较为好用的电脑监控软件推荐。 1. 安企神 7天试用体验https://work.weixin.qq.com/ca/cawcde06a33907e60a 简介&#xff1a;安企神是一款专为企业设计的信息安全管理软件&#xff0c;提供…

算法_队列+宽度优先搜索

文章目录 前言N叉树的层序遍历题目要求题目解析代码如下 二叉树最大宽度题目要求题目解析代码如下 在每个树中找最大值题目要求题目解析代码如下 二叉树的锯齿形层序遍历题目要求题目解析代码如下 前言 本文将会向你介绍有关队列宽度优先搜索的题目&#xff1a;N叉树的层序遍历…

目标检测-RT-DETR

RT-DETR (Real-Time Detection Transformer) 是一种结合了 Transformer 和实时目标检测的创新模型架构。它旨在解决现有目标检测模型在速度和精度之间的权衡问题&#xff0c;通过引入高效的 Transformer 模块和优化的检测头&#xff0c;提升了模型的实时性和准确性。RT-DETR 可…

Linux-实用指令

目录 前言 指定运行级别 基本介绍 切换运行级别 指令类 帮助指令 man 获得帮助信息 help指令 文件目录类 pwd指令 ls指令 cd指令 mkdir命令 rmdir指令删除空目录 touch指令 cp指令 rm指令 mv指令 cat指令 more指令 less指令 echo指令 head指令 tail指令…

2024.9.6 作业

手写unique_ptr指针指针 代码&#xff1a; #include <iostream> #include <stdexcept>template <typename T> class unique_ptr { public:// 构造函数explicit unique_ptr(T* ptr nullptr) : m_ptr(ptr) {}// 析构函数~unique_ptr() {delete m_ptr;}// 禁…

设置GB/T35114服务

GB/T35114服务是下联模式&#xff0c;支持GB/T35114标准A级双向认证&#xff0c;支持国密系列硬件设备。 操作步骤 在配置-》设备-》级联配置-》GB服务配置 进行编辑。 1、点击 编辑 2、修改国标服务器地址 3、如果其他参数也需要修改&#xff0c;都可自定义&#xff0c;除了国…

FME教程:通过更新读模块,解决FME读取shapefile数据,提示意外输入,“在转换中,某些读取的要素与工作空间的要素类不匹配……”的问题

目录 一、问题情况 二、解决方法 一、问题情况 在使用制作好的FME模板读取shapefile数据时&#xff0c;有时候会遇到弹窗提示意外输入&#xff0c;模板无法运行&#xff0c;在日志信息中警示“在转换中&#xff0c;某些读取的要素与工作空间的要素类不匹配。可能由于读模块的…

2024年全国大学生数学建模竞赛(E题) 建模解析|交通流量管控|小鹿学长带队指引全代码文章与思路

我是鹿鹿学长&#xff0c;就读于上海交通大学&#xff0c;截至目前已经帮200人完成了建模与思路的构建的处理了&#xff5e; 本篇文章是鹿鹿学长经过深度思考&#xff0c;独辟蹊径&#xff0c;实现综合建模。独创复杂系统视角&#xff0c;帮助你解决国赛的难关呀。 完整内容可以…

【前端学习】AntV G6-06 使用图算法

课程链接 图算法 Algorithm | G6 (antgroup.com) 【例子 pageRank】 ​​​​​​力导向图布局 | G6 (antgroup.com) 重点部分添加注释 import G6 from antv/g6;const { pageRank } G6.Algorithm; // 在此引入 pageRankconst container document.getElementById(containe…

无人机之报警器的作用

一、紧急救援与辅助搜救 紧急救援&#xff1a;在事故或紧急情况下&#xff0c;无人机报警器可以迅速发出警报&#xff0c;指引救援人员前往事故地点&#xff0c;提高救援效率。 辅助搜救&#xff1a;无人机搭载报警器可以辅助寻找失踪人员或其他需要搜救的场景&#xff0c;通…

MySQL数据库的介绍

目录 1.什么是MySQL数据库 2.MySQL数据库的设计 MySQL的进一步认识 MySQL的客户端 —— mysql MySQL的服务端 —— mysqld 3.MySQL数据库的架构 MySQL架构图 连接层 服务层 存储引擎层 文件系统层 4.MySQL的存储引擎 认识存储引擎 MySQL中的存储引擎 存储引擎之…

电工类 ,今日行业动态

电工类今日行业动态 一、技术发展趋势 智能化、自动化推进&#xff1a;随着人工智能、物联网等技术的不断发展&#xff0c;电工行业正逐步向智能化、自动化转型。智能电网、智能家居等领域的快速发展&#xff0c;对电工技术提出了新的要求&#xff0c;电工人员需要不断学习和…

使用matplotlib绘制散点图、柱状图和饼状图-学习篇

一、散点图 Python代码如下&#xff1a; num_points 100 x np.random.rand(num_points) #x点位随机 y np.random.rand(num_points) #y点位随机 colors np.random.rand(num_points) #颜色随机 sizes 1000 * np.random.rand(num_points) # 大小随机 alphas np.random.ran…

网络安全评测评技术与标准

网络安全测评概况 概念 参照一定的标准规范要求&#xff0c;通过一系列技术和管理方法&#xff0c;获取评估对象网络安全状况信息&#xff0c;对其给出相应网络安全情况综合判定 测评对象&#xff1a;信息系统的组成要素或信息系统自身 CC&#xff08;Common Criteria&#…

Versioned Staged Flow-Sensitive Pointer Analysis

VSFS 1.Introduction2.Approach2.1.相关概念2.2.VSFS 3.Evaluation参考文献 1.Introduction 上一篇blog我介绍了目前flow-sensitive pointer analysis常用的SFS算法。相比IFDS-based方法&#xff0c;SFS显著通过稀疏分析提升了效率&#xff0c;但是其内部依旧有许多冗余计算&a…

12道经典性能测试人员面试题

1.性能测试包含了哪些软件测试&#xff08;至少举出3种&#xff09;&#xff1f; 参考答案&#xff1a;负载测试、压力测试、容量测试。 负载测试&#xff08;Load Testing&#xff09;&#xff1a;负载测试是一种主要为了测试软件系统是否达到需求文档设计的目标&#xff0c…

Linux系统编程实现ls -l | wc -l指令

由于该指令是通过管道的形式实现的&#xff0c;所以我们要使用系统函数pipe。ls -l |wc -l的作用就是统计当前目录有多少文件。如果又父进程实现ls -l&#xff0c;子进程实现wc -l指令&#xff0c;代码如下&#xff1a; #include<unistd.h> #include<stdio.h> #in…

帝可得智能售货机运营管理系统

1.项目介绍 帝可得是一个基于物联网概念下的智能售货机运营管理系统 应用场景&#xff1a;智能家居、共享充电中、智能售货机 智能售货机的优势在于其自我管理能力 。 物联网技术&#xff1a;像是售货机的顺风耳和千里眼。 智能分析与推荐 人员设备绑定管理 移动支付支持…