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

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

在上一篇文章里,我们实现了添加负面效果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()); //获取到战斗接口//通过函数库获取角色身上的ASCif(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和ASAbilitySystemComponent = PlayerStateBase->GetAbilitySystemComponent();AttributeSet = PlayerStateBase->GetAttributeSet();//初始化ASCAbilitySystemComponent->InitAbilityActorInfo(PlayerStateBase, this);//触发Actor的技能信息设置回调Cast<URPGAbilitySystemComponent>(AbilitySystemComponent)->AbilityActorInfoSet(); //获取PCif(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. 在激活负面效果时,角色死亡是否能够自动停止激活等待销毁。
    如果都没有问题,基本上效果实现完毕。

相关文章:

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

在上一篇文章里&#xff0c;我们实现了添加负面效果GE&#xff0c;并且在添加GE时&#xff0c;也会给角色应用一个负面效果标签作为标识。在这一篇里&#xff0c;我们将通过负面效果标签标识&#xff0c;应用角色身上展现对应的负面效果的表现。 我们将在这篇文章里添加一个自定…...

TCP 和 UDP 区别

UDP UDP&#xff08;用户数据报协议&#xff0c;User Datagram Protocol&#xff09;是一种无连接的网络传输协议&#xff0c;提供了简单的消息传送服务。UDP位于传输层&#xff0c;允许应用程序向其他主机发送封装在IP数据报中的消息&#xff0c;而无需先建立连接。由于UDP不…...

免费2024柜台租赁经营合同范本模板下载分享

今天看到这个合同范本都拿来卖钱,我直接分享出来2024年最新的范本模板随便下,免费的 柜台租赁经营合同GF—2013—0603.docx: https://url51.ctfile.com/f/20096151-1353625109-4285d2?p1605 (访问密码: 1605) 柜台租赁经营合同GF—2013—0603.pdf: https://url51.ctfile.com/…...

模型和算力看板:Compute DashBoard

AGI 之路 AGI&#xff08;通用人工智能&#xff09;是整个计算机科学的圣杯&#xff0c;算力的增长和模型能力的提升&#xff08;算法和数据&#xff09;缺一不可。作为一个新质生产力&#xff0c;构建一个合理的评价体系是常用的方法论。针对模型和算力的评价&#xff0c;有类…...

Python加载 TorchScript 格式的 ResNet18 模型分类该模型进行预测并输出预测的类别和置信度

首先加载预训练的 ResNet18 模型。将模型设置为评估模式&#xff0c;以确保特定层&#xff08;如 Dropout 和 BatchNorm&#xff09;在评估时具有确定性的行为。创建一个形状为 (1, 3, 224, 224) 的随机张量作为示例输入。使用 torch.jit.trace 函数追踪模型在给定示例输入上的…...

学习笔记--MybatisPlus

官网&#xff1a;MyBatis-Plus &#x1f680; 为简化开发而生 快速入门 入门案例 引入MybatisPlus的起步依赖 定义Mapper 问题&#xff1a; MybatisPlus中Invalid bound statement (not found): com.itheima.mp.mapper.UserMapper.insert 一定要指定实体类&#xff01;&am…...

【机器学习】XGBoost的用法和参数解释

一、XGBoost的用法 流程&#xff1a; 代码案例&#xff1a; 二、XGBoost的几大参数 1、一般参数&#xff0c;用于集成算法本身 ①n_estimators 集成算法通过在数据上构建多个弱 评估器&#xff0c;汇总所有弱评估器的建模结果&#xff0c;以获取比单个模型更好的回归或分类…...

Vivado 约束

步骤5&#xff1a;保存约束 约束管理是设计流程的重要一步&#xff0c;Vivado设计套件 为您提供了在现有约束文件中添加新约束、覆盖的灵活性 现有约束&#xff0c;或创建新的约束文件以跟踪设计更改或完成 缺少约束。 您为设计创建了一些定时异常&#xff0c;但这些异常仅存在…...

如何在Excel中创建一个VBA宏,并设置一个按钮来执行这个宏

下面是一个详细的步骤指南 步骤1&#xff1a;创建VBA宏 1. 打开Excel并按 Alt F11 打开VBA编辑器。 2. 在VBA编辑器中&#xff0c;选择 Insert > Module 来插入一个新的模块。 3. 将以下代码粘贴到模块中&#xff1a; vba Sub CreateNewSheet() 声明一个工作表对象Dim …...

H3C SR-MPLS通过OSPF通告SID配置

首先在配置前理解几个基本概念 Prefix SID配置 统一分配和配置&#xff08;全局规划&#xff09;loopback和prefix sidPrefix SIDSRGB Base&#xff08;16000&#xff09;index Adj SID自动生成 对应SR节点间的互联链路SR节点本地标识&#xff0c;从设备本地Segment池中动态…...

JS面试真题 part2

JS面试真题 part2 6、typeof 与 instanceof 区别7、JavaScript原型&#xff0c;原型链&#xff1f;有什么特点8、说说你对作用域链的理解9、谈谈this对象的理解10、说说new操作符具体干了什么 6、typeof 与 instanceof 区别 自己回答&#xff1a; typeof&#xff1a;用来判断数…...

python 下载excel 添加水印

Python 在 Excel 中添加水印 https://zhuanlan.zhihu.com/p/499239298 生成图片 from PIL import Image, ImageDraw, ImageFont import numpy as np import matplotlib.pyplot as plt# 创建一个新的白色图片 img Image.new(RGB, (200, 100), color(255, 255, 255))# 指定中…...

CosyVoice:开源强大的 AI 语音合成工具

在当今科技飞速发展的时代&#xff0c;AI 语音合成技术正逐渐改变着我们的生活。今天&#xff0c;就为大家介绍一款卓越的语音合成工具——CosyVoice。 一、安装步骤 克隆和安装&#xff1a; 克隆仓库&#xff1a;git clone --recursive https://github.com/FunAudioLLM/Cos…...

【靶场】Pikachu—XSS Cross-Site Scripting(前五关)

&#x1f3d8;️个人主页&#xff1a; 点燃银河尽头的篝火(●’◡’●) 如果文章有帮到你的话记得点赞&#x1f44d;收藏&#x1f497;支持一下哦 【靶场】Pikachu—XSS Cross-Site Scripting&#xff08;前五关&#xff09; 第一关 反射型xss(get)第二关 反射型xss(post)第三关…...

Dance with Compiler - EP2

今天来熟悉汇编指令。 基本指令特点 str: store value to memory ldr: load value from memory stp: store register value to stack ldp: load stack value to register 更新寄存器的操作&#xff0c;一般结果寄存器是左操作数。 写内存的操作&#xff08;str&#xff09;&…...

微博视频无水印下载的方法

在如今的数字时代&#xff0c;社交媒体平台如微博已经成为人们分享日常生活、获取新闻和娱乐内容的重要渠道。我们时常会在刷微博时看到一些有趣的视频图片&#xff0c;或是名人的访谈&#xff0c;或是搞笑的短片&#xff0c;有时甚至是一些珍贵的历史资料。这些视频不仅内容丰…...

C语言 | Leetcode C语言题解之第390题消除游戏

题目&#xff1a; 题解&#xff1a; int lastRemaining(int n) {int a1 1;int k 0, cnt n, step 1;while (cnt > 1) {if (k % 2 0) { // 正向a1 a1 step;} else { // 反向a1 (cnt % 2 0) ? a1 : a1 step;}k;cnt cnt >> 1;step step << 1;}return …...

虚拟现实辅助工程技术助力多学科协同评估

在当今高速发展的经济环境中&#xff0c;制造业面临着多重挑战&#xff0c;包括提高产品性能、压缩设计周期、实现轻量化设计和降低成本。为了有效应对这些挑战&#xff0c;多学科协同评估成为缩短研发周期和提升研制质量的关键手段。 传统的多学科评估面临着数据孤立与融合困难…...

Java获取小程序码示例(三种小程序码)

首先我们可以看到官方文档上是有三种码的 获取小程序码 这里特别要注意的是第一种和第三种是有数量限制的&#xff0c;所以大家生成的时候记得保存&#xff0c;也不要一直瞎生成 还有一点要注意的是第一种和第二种是太阳码 第三种是方形码 好了直接上代码 这里要注意&#xff…...

【最新华为OD机试E卷-支持在线评测】分糖果(100分)-多语言题解-(Python/C/JavaScript/Java/Cpp)

🍭 大家好这里是春秋招笔试突围 ,一枚热爱算法的程序员 ✨ 本系列打算持续跟新华为OD-E/D卷的三语言AC题解 💻 ACM金牌🏅️团队| 多次AK大厂笔试 | 编程一对一辅导 👏 感谢大家的订阅➕ 和 喜欢💗 🍿 最新华为OD机试D卷目录,全、新、准,题目覆盖率达 95% 以上,…...

uniapp 对接腾讯云IM群组成员管理(增删改查)

UniApp 实战&#xff1a;腾讯云IM群组成员管理&#xff08;增删改查&#xff09; 一、前言 在社交类App开发中&#xff0c;群组成员管理是核心功能之一。本文将基于UniApp框架&#xff0c;结合腾讯云IM SDK&#xff0c;详细讲解如何实现群组成员的增删改查全流程。 权限校验…...

基于距离变化能量开销动态调整的WSN低功耗拓扑控制开销算法matlab仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.算法仿真参数 5.算法理论概述 6.参考文献 7.完整程序 1.程序功能描述 通过动态调整节点通信的能量开销&#xff0c;平衡网络负载&#xff0c;延长WSN生命周期。具体通过建立基于距离的能量消耗模型&am…...

从WWDC看苹果产品发展的规律

WWDC 是苹果公司一年一度面向全球开发者的盛会&#xff0c;其主题演讲展现了苹果在产品设计、技术路线、用户体验和生态系统构建上的核心理念与演进脉络。我们借助 ChatGPT Deep Research 工具&#xff0c;对过去十年 WWDC 主题演讲内容进行了系统化分析&#xff0c;形成了这份…...

Linux相关概念和易错知识点(42)(TCP的连接管理、可靠性、面临复杂网络的处理)

目录 1.TCP的连接管理机制&#xff08;1&#xff09;三次握手①握手过程②对握手过程的理解 &#xff08;2&#xff09;四次挥手&#xff08;3&#xff09;握手和挥手的触发&#xff08;4&#xff09;状态切换①挥手过程中状态的切换②握手过程中状态的切换 2.TCP的可靠性&…...

django filter 统计数量 按属性去重

在Django中&#xff0c;如果你想要根据某个属性对查询集进行去重并统计数量&#xff0c;你可以使用values()方法配合annotate()方法来实现。这里有两种常见的方法来完成这个需求&#xff1a; 方法1&#xff1a;使用annotate()和Count 假设你有一个模型Item&#xff0c;并且你想…...

视频字幕质量评估的大规模细粒度基准

大家读完觉得有帮助记得关注和点赞&#xff01;&#xff01;&#xff01; 摘要 视频字幕在文本到视频生成任务中起着至关重要的作用&#xff0c;因为它们的质量直接影响所生成视频的语义连贯性和视觉保真度。尽管大型视觉-语言模型&#xff08;VLMs&#xff09;在字幕生成方面…...

ElasticSearch搜索引擎之倒排索引及其底层算法

文章目录 一、搜索引擎1、什么是搜索引擎?2、搜索引擎的分类3、常用的搜索引擎4、搜索引擎的特点二、倒排索引1、简介2、为什么倒排索引不用B+树1.创建时间长,文件大。2.其次,树深,IO次数可怕。3.索引可能会失效。4.精准度差。三. 倒排索引四、算法1、Term Index的算法2、 …...

网络编程(UDP编程)

思维导图 UDP基础编程&#xff08;单播&#xff09; 1.流程图 服务器&#xff1a;短信的接收方 创建套接字 (socket)-----------------------------------------》有手机指定网络信息-----------------------------------------------》有号码绑定套接字 (bind)--------------…...

rnn判断string中第一次出现a的下标

# coding:utf8 import torch import torch.nn as nn import numpy as np import random import json""" 基于pytorch的网络编写 实现一个RNN网络完成多分类任务 判断字符 a 第一次出现在字符串中的位置 """class TorchModel(nn.Module):def __in…...

使用LangGraph和LangSmith构建多智能体人工智能系统

现在&#xff0c;通过组合几个较小的子智能体来创建一个强大的人工智能智能体正成为一种趋势。但这也带来了一些挑战&#xff0c;比如减少幻觉、管理对话流程、在测试期间留意智能体的工作方式、允许人工介入以及评估其性能。你需要进行大量的反复试验。 在这篇博客〔原作者&a…...