104. UE5 GAS RPG 实现技能火焰爆炸

这一篇文章我们再实现一个技能火焰爆炸,由于我们之前已经实现了三个玩家技能,这一个技能有一些总结的味道,对于创建技能相同的部分,长话短说,我们过一遍。

准备工作

我们需要一个技能类,继承于伤害技能基类
在这里插入图片描述
主要在里面覆写一下技能描述
在这里插入图片描述
接下来主要是实现

FString URPGFireBlast::GetDescriptionAtLevel(const int32 Level, const FString& Title)
{const int32 Damage = GetDamageByDamageType(Level, FRPGGameplayTags::Get().Damage_Fire);const float ManaCost = GetManaCost(Level);const float Cooldown = GetCooldown(Level);return FString::Printf(TEXT(// 标题"<Title>%s</>\n"// 细节"<Small>等级:</> <Level>%i</>\n""<Small>技能冷却:</> <Cooldown>%.1f</>\n""<Small>蓝量消耗:</> <ManaCost>%.1f</>\n\n"//%.1f会四舍五入到小数点后一位// 技能描述"<Default>向四面八方发射 %i 颗火球,每颗火球会在返回时发生爆炸,并造成</> <Damage>%i</> <Default>点径向火焰伤害,并有一定几率触发燃烧。</>"),// 动态修改值*Title,Level,Cooldown,-ManaCost,NumFireBalls,Damage);
}

然后,创建一个蓝图类,用于实现技能逻辑,技能逻辑在下面再实现,我们将装配,伤害,等相关的实现。
在这里插入图片描述
技能需要创建两个标签,一个是技能的标识标签,通过标签可以获取到此技能,另一个就是技能对应的冷却标签,我们直接通过标签管理器创建即可。
在这里插入图片描述
技能的标识标签需要在代码中获取,我们需要在代码中创建
在这里插入图片描述
有了技能蓝图和标签,我们再技能数据资产将数据添加,后续可以通过此来获取数据,显示到ui,等。
在这里插入图片描述

在技能面板的技能按钮,将需要显示此技能的按钮的技能tag设置为对应技能tag
在这里插入图片描述
接下来,就是实现技能的伤害,冷却和消耗,对于伤害和消耗,我们需要在对应的图表CT_Damage和CT_SpellCost里增加对应的表格内容。
在这里插入图片描述
在技能蓝图里,设置对应的技能伤害GE,这个我们是通用的,然后引用伤害
在这里插入图片描述
并将标签设置
在这里插入图片描述
接着创建两个GE,实现冷却和消耗
在这里插入图片描述
冷却还是之前思路,添加标签实现
在这里插入图片描述
消耗去修改属性,这种也不是必须的,我们在技能里调用CommitAbility之前可以设置,或者实现一种自动计算的方式都可以。
在这里插入图片描述
然后设置给技能
在这里插入图片描述

接下来就是运行测试效果是否符合预期
在这里插入图片描述
为了方便后续测试,我们将技能直接放置到技能栏,首先设置技能的输入标签
在这里插入图片描述
然后在初始技能数组里添加对应的技能
在这里插入图片描述

添加火球

接下来,我们实现技能的表现效果,技能会平均角度,向角色的四面八方移动,然后移动到一定距离,自动返回并发生爆炸。实现这个效果,我们无法通过使用内置的方法,需要使用时间轴来实现效果。
基于之前的火球术的实现,我们创建一个对应的火球的子类
在这里插入图片描述
命名一下
在这里插入图片描述
在类里,我们覆写beginPlay函数,并添加一个蓝图实现

/*** 火焰爆发使用的火球类*/
UCLASS()
class RPG_API ARPGFireBall : public AProjectile
{GENERATED_BODY()public://执行蓝图时间轴事件,需要在蓝图中实现此事件UFUNCTION(BlueprintImplementableEvent)void StartOutgoingTimeline();UPROPERTY(BlueprintReadOnly) //当前火球返回的目标角色,默认是技能的释放者,在创建火球是创建TObjectPtr<AActor> ReturnToActor;
protected:virtual void BeginPlay() override;

在游戏开始事件里调用时间轴事件

void ARPGFireBall::BeginPlay()
{Super::BeginPlay();StartOutgoingTimeline(); //调用开始时间线修改
}

编译打开UE创建一个对应的蓝图类
在这里插入图片描述
添加一个Niagara组件,用于显示粒子效果
在这里插入图片描述
设置爆炸效果和音效配置
在这里插入图片描述
因为我们需要使用时间轴实现,内置的自动移动的相关可以关闭
在这里插入图片描述
关闭帧更新
在这里插入图片描述
我们也不需要自动激活
在这里插入图片描述
在火球蓝图里,我们实现时间轴事件,首先获取到初始位置和火球移动的最远目标位置
在这里插入图片描述
在后面,我们首先实现火球从初始位置移动到终点位置,通过时间轴实现
在这里插入图片描述
时间轴里面设置了一个值,这个值采用现快后慢的方式,这样火球有一种减速的效果。值是0-1,我们可以通过插值的方式实现位置从起点到终点。
在这里插入图片描述
在上一个时间轴执行完成之后,我们再运行一个时间轴,这个事件轴是实现角色返回到角色的当前位置,所以,我们修改为了从终点位置向玩家角色位置插值,这里将当前玩家的位置进行了保存,方便后续使用
在这里插入图片描述
这个时间轴的线是先慢后快
在这里插入图片描述
最后,我们在返回更新时,如果火球和角色的距离小于某个阈值,那么将自我销毁,防止火球攻击自身
在这里插入图片描述
对于这种相乘的我们可以转换类型
在这里插入图片描述
这是转换成浮点类型的效果
在这里插入图片描述

修改技能类实现表现效果

接着,我们修改技能实现效果,我们在技能里设置一个参数,用于设置火球类

private:UPROPERTY(EditDefaultsOnly, Category="FireBlast") //生成火球使用的类TSubclassOf<ARPGFireBall> FireBallClass;

编译,在技能蓝图类里设置我们创建的火球蓝图类
在这里插入图片描述
接着,我们在技能类里创建一个生成火球的函数,这个函数里,可以生成技能所需的火球

	/*** 生成技能所需的火球* @return NumFireBalls个数火球的数组*/UFUNCTION(BlueprintCallable)TArray<ARPGFireBall*> SpawnFireBall();

在代码实现里,我们获取到角色的位置和朝向,通过之前创建的函数,获取到每个火球的旋转值,并通过旋转值创建火球,生成所需的参数。

TArray<ARPGFireBall*> URPGFireBlast::SpawnFireBall()
{//获取到角色朝向和位置const FVector Forward = GetAvatarActorFromActorInfo()->GetActorForwardVector();const FVector Location = GetAvatarActorFromActorInfo()->GetActorLocation();//通过函数获取到每个需要生成的火球的旋转TArray<FRotator> Rotators = URPGAbilitySystemLibrary::EvenlySpacedRotators(Forward, FVector::UpVector, 360.f, NumFireBalls);TArray<ARPGFireBall*> FireBalls; //生成所需的火球数组for(const FRotator& Rotator : Rotators){//创建变换FTransform SpawnTransform;SpawnTransform.SetLocation(Location);SpawnTransform.SetRotation(Rotator.Quaternion());//创建火球 使用 SpawnActorDeferred 来生成对象时,UE 会延迟实际的对象生成过程,这样你有机会在完全初始化对象之前进行自定义配置。ARPGFireBall* FireBall = GetWorld()->SpawnActorDeferred<ARPGFireBall>(FireBallClass,SpawnTransform,GetOwningActorFromActorInfo(),CurrentActorInfo->PlayerController->GetPawn(),ESpawnActorCollisionHandlingMethod::AlwaysSpawn);//设置火球的伤害配置FireBall->DamageEffectParams = MakeDamageEffectParamsFromClassDefaults();FireBall->ReturnToActor = GetAvatarActorFromActorInfo();FireBalls.Add(FireBall);//在配置完成火球配置后,调用FinishSpawning将火球正式添加到场景中FireBall->FinishSpawning(SpawnTransform);}return FireBalls;
}

然后在技能蓝图里调用函数
在这里插入图片描述
接下来就是运行查看效果
在这里插入图片描述

实现伤害

接下来,我们实现技能的伤害,伤害分为两种,一种是火球在行进当中与敌人触碰造成的伤害,另一种是在火球靠近释放者一定范围后,销毁时产生的爆炸。

我们首先实现行进中与敌人产生碰撞造成的伤害。
首先,我们配置技能的蓝图的配置,设置对应的伤害以及伤害类型。
在这里插入图片描述
接着,我们要在c++中,覆写OnSphereOverlap函数,实现在移动过程中造成的伤害。这里,我们基于ARPGFireBlot重写,去掉了与敌人产生重叠后的销毁火球的事件,而是应用一个伤害GE,由于火球没有伤害击退效果,这里我们去掉了相关代码。

void ARPGFireBall::OnSphereOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{if(GetInstigator() == OtherActor) return; //判断和碰撞体接触的目标是否为自身//如果不是敌人,将不执行后续if(!URPGAbilitySystemLibrary::IsNotFriend(GetInstigator(), OtherActor)) return;//目标未继承战斗接口,返回if(!OtherActor->Implements<UCombatInterface>()) return;//播放击中特效 当前服务器端未调用销毁时,直接播放if(!bHit) PlayImpact();//在重叠后,销毁自身if(HasAuthority()) //是否为服务器,如果服务器端,将执行应用GE,并通过GE的自动同步到客户端{//为目标应用GEif(UAbilitySystemComponent* TargetASC = UAbilitySystemBlueprintLibrary::GetAbilitySystemComponent(OtherActor)){//死亡冲击的力度和方向DamageEffectParams.DeathImpulse = GetActorForwardVector() * DamageEffectParams.DeathImpulseMagnitude;//通过配置项应用给目标ASCDamageEffectParams.TargetAbilitySystemComponent = TargetASC;URPGAbilitySystemLibrary::ApplyDamageEffect(DamageEffectParams);}}
}

接下来则是实现火球移动结束后的爆炸效果,这个效果实现,我们需要修改伤害配置项,将其修改为范围伤害,这里采用的是增加一些修改对应配置的函数,然后在蓝图调用实现配置项的修改,然后应用给目标。
这里,我们在函数库里增加了四个函数,用于修改伤害配置项的范围伤害参数,击退,死亡时的击退以及攻击敌人的ASC的函数

	/*** 修改伤害配置项,将其设置为具有范围伤害的配置项* @param DamageEffectParams 需要修改的配置项* @param bIsRadial 设置是否为范围伤害* @param InnerRadius 内半径* @param OutRadius 外半径* @param Origin 伤害中心*/UFUNCTION(BlueprintCallable, Category="RPGAbilitySystemLibrary|GameplayEffects")static void SetIsRadialDamageEffectParams(UPARAM(ref) FDamageEffectParams& DamageEffectParams, bool bIsRadial, float InnerRadius, float OutRadius, FVector Origin);/*** 修改伤害的冲击力的方向* @param DamageEffectParams 需要修改的伤害配置项* @param KnockbackDirection 攻击时触发击退的方向*/UFUNCTION(BlueprintCallable, Category="RPGAbilitySystemLibrary|GameplayEffects")static void SetKnockbackDirection(UPARAM(ref) FDamageEffectParams& DamageEffectParams, FVector KnockbackDirection, float Magnitude = 0.f);/*** 修改伤害的冲击力的方向* @param DamageEffectParams 需要修改的伤害配置项* @param ImpulseDirection 死亡时触发击退的方向*/UFUNCTION(BlueprintCallable, Category="RPGAbilitySystemLibrary|GameplayEffects")static void SetDeathImpulseDirection(UPARAM(ref) FDamageEffectParams& DamageEffectParams, FVector ImpulseDirection, float Magnitude = 0.f);/*** 设置伤害配置应用目标ASC* @param DamageEffectParams 需要修改的伤害配置 * @param InASC 应用目标ASC*/UFUNCTION(BlueprintCallable, Category="RPGAbilitySystemLibrary|GameplayEffects")static void SetEffectParamsTargetASC(UPARAM(ref) FDamageEffectParams& DamageEffectParams, UAbilitySystemComponent* InASC);

接着,我们实现对配置项的修改

void URPGAbilitySystemLibrary::SetIsRadialDamageEffectParams(FDamageEffectParams& DamageEffectParams, bool bIsRadial, float InnerRadius, float OutRadius, FVector Origin)
{DamageEffectParams.bIsRadialDamage = bIsRadial;DamageEffectParams.RadialDamageInnerRadius = InnerRadius;DamageEffectParams.RadialDamageOuterRadius = OutRadius;DamageEffectParams.RadialDamageOrigin = Origin;
}void URPGAbilitySystemLibrary::SetKnockbackDirection(FDamageEffectParams& DamageEffectParams, FVector KnockbackDirection, float Magnitude)
{KnockbackDirection.Normalize();if(Magnitude == 0.f){DamageEffectParams.KnockbackForce = KnockbackDirection * DamageEffectParams.KnockbackForceMagnitude;}else{DamageEffectParams.KnockbackForce = KnockbackDirection * Magnitude;}
}void URPGAbilitySystemLibrary::SetDeathImpulseDirection(FDamageEffectParams& DamageEffectParams, FVector ImpulseDirection, float Magnitude)
{ImpulseDirection.Normalize();if(Magnitude == 0.f){DamageEffectParams.DeathImpulse = ImpulseDirection * DamageEffectParams.DeathImpulseMagnitude;}else{DamageEffectParams.DeathImpulse = ImpulseDirection * Magnitude;}
}void URPGAbilitySystemLibrary::SetEffectParamsTargetASC(FDamageEffectParams& DamageEffectParams, UAbilitySystemComponent* InASC)
{DamageEffectParams.TargetAbilitySystemComponent = InASC;
}

接着,我们编译代码,打开火球蓝图,在触发火球爆炸后,实现对应逻辑
在这里插入图片描述
我们将后面的逻辑封装为了一个函数,这个函数内主要逻辑是设置技能造成的范围伤害相关参数,以及获取到需要应用伤害的目标,然后调用函数应用,销毁自身。
在这里插入图片描述
应用伤害的函数看似很长,其实主要就是遍历伤害数组,然后修改应用目标的ASC,以及击退相关参数,这里对每个目标的值都不一样。最后调用函数库函数应用即可。
在这里插入图片描述

修改爆炸使用GameplayCue实现

我们实现了伤害,这里再修改爆炸时的爆炸效果,我们采用通过c++调用,然后使用GameplayCue实现。
我们在c++里增加一个新的标签,这个火焰爆炸的GameplayCue可以通过此标签调用

FGameplayTag GameplayCue_FireBlast; //火焰爆炸火球爆炸时的表现效果
	GameplayTags.GameplayCue_FireBlast = UGameplayTagsManager::Get().AddNativeGameplayTag(FName("GameplayCue.FireBlast"),FString("火焰爆炸表现效果标签"));

我们需要覆写RPGFireBall的PlayImpact函数

virtual void PlayImpact() override;

实现这里,我们将通过UGameplayCueManager去调用GameplayCue,而不是之前的方式。

void ARPGFireBall::PlayImpact()
{if(GetOwner()){//设置GameplayCue播放位置FGameplayCueParameters Parameters;Parameters.Location = GetActorLocation();UGameplayCueManager::ExecuteGameplayCue_NonReplicated(GetOwner(), FRPGGameplayTags::Get().GameplayCue_FireBlast, Parameters);}//将音乐停止后会自动销毁if(LoopingSoundComponent){//循环组件暂停并销毁LoopingSoundComponent->Stop();LoopingSoundComponent->DestroyComponent();}bHit = true;
}

接着编译打开蓝图,创建一个对应的GameplayCue
在这里插入图片描述
设置应用标签
在这里插入图片描述
然后设置粒子系统和爆炸音效。
在这里插入图片描述

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

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

相关文章

【力扣打卡系列】验证二叉搜索树

坚持按题型打卡&刷&梳理力扣算法题系列&#xff0c;语言为go&#xff0c;Day17 验证二叉搜索树 题目描述 解题思路 前序遍历&#xff1a;先访问节点值&#xff0c;再访问左右子树有效二叉搜索树的定义 节点的左子树只包含小于当前节点的数节点的右子树只包含大于当前节…

Swarm-LIO: Decentralized Swarm LiDAR-inertial Odometry论文翻译

文章目录 前言一、介绍二、相关工作三、方法A. 问题表述B. 框架概述C. 群体系统的初始化D. 去中心化激光雷达-惯性状态估计 四. 实验A. 室内飞行B. 退化环境飞行C. 去中心化部署 五. 结论和未来工作 前言 原文&#xff1a;原文 准确的自我状态和相对状态估计是完成群体任务的关…

京东毫秒级热key探测框架JD-hotkey

前言 对任意突发性的&#xff0c;无法预先感知的热点数据&#xff0c;包括热点数据&#xff08;如突发大量请求同一个商品&#xff09;、热用户&#xff08;如恶意爬虫刷子&#xff09;、热接口&#xff08;突发海量请求同一个接口&#xff09;等&#xff0c;一瞬间打到我们的服…

IntelliJ IDEA 中上传项目到 Gitee 的完整指南

博主主页:【南鸢1.0】 本文专栏&#xff1a;git 目录 简介 1.插入intellij-gitee 2.导入下载插件 3.选择导航栏中的VCS->Share Project on Gitee 4.登录gitee 6.验证gitee仓库是否创建成功 7.上传分享项目 8.验证仓库代码是否上传成功 总结 简介 Gitee 是一个代码…

低代码可视化-按钮open-type开放能力自定义-代码生成器

微信小程序原本确实不直接支持通过点击按钮将内容分享到朋友圈的功能&#xff0c;但微信在后续更新中逐步放开了部分限制&#xff0c;允许特定内容以小程序卡片的形式分享到朋友圈。然而&#xff0c;这一功能仍然需要满足一定的条件&#xff0c;并且需要开发者进行特定的配置。…

基于springboot乐器视频学习网站设计与实现(源码齐全可用)

项目描述 临近学期结束&#xff0c;还是毕业设计&#xff0c;你还在做java程序网络编程&#xff0c;期末作业&#xff0c;老师的作业要求觉得大了吗?不知道毕业设计该怎么办?网页功能的数量是否太多?没有合适的类型或系统?等等。你想解决的问题&#xff0c;今天给大家介绍…

TypeScript:never 类型的神奇妙用

在 TypeScript 中&#xff0c;never 是一个特殊类型&#xff0c;表示「永不存在的值类型」&#xff0c;通常用于表示不可能发生的情况。它适用于抛出异常、不返回值的函数或处理逻辑上永远不会出现的分支。 以下是它的简单用法和注意事项&#xff1a; 1. never 的用法 1、抛…

Redis-结构化value对象的类型

文章目录 一、Redis的结构化value对象类型的介绍二、Redis的这些结构化value对象类型的通用操作查看指定key的数据类型查看所有的key判断指定key是否存在为已存在的key进行重命名为指定key设置存活时间pexpire与expire 查看指定Key的存活时间为指定key设置成永久存活 三、Redis…

解密美国 VPS 主机的核心优势与未来发展

在全球网络需求不断增长的今天&#xff0c;许多企业和开发者都在寻找更灵活、安全、性能优异的主机解决方案。美国 VPS 主机凭借其强大的技术支持和广泛的网络连接&#xff0c;成为国际用户的热门选择。本文将深入探讨美国 VPS 主机的核心优势、其在网络应用上的独特表现&#…

XSS小游戏【1-13关】

第一关 Payload&#xff1a;<script>alert(1)</script> 第二关 Payload&#xff1a;keyword<script>alert(1)</script> 发现没有成功&#xff0c;F12发现需要闭合input 标签 再次输入payload&#xff1a;aaa"><svg οnlοadalert(1)> …

Spring Boot框架:校园社团信息管理的现代化解决方案

3系统分析 3.1可行性分析 通过对本校园社团信息管理系统实行的目的初步调查和分析&#xff0c;提出可行性方案并对其一一进行论证。我们在这里主要从技术可行性、经济可行性、操作可行性等方面进行分析。 3.1.1技术可行性 本校园社团信息管理系统采用SSM框架&#xff0c;JAVA作…

uniapp推送配置流程

Dcloud Dcloud注册账号 个推 了解即可 注册个推账号 ios配置流程 需配置含有推送的描述文件以及p8证书 配置推送证书 ios证书配置报技术错误&#xff08;参数错误&#xff09; TeamID-苹果开发者账号唯一的ID 安卓需配置多厂商 小米手机需要配置小米厂商 华为手机则需…

JavaEE初阶---网络原理之TCP篇(二)

文章目录 1.断开连接--四次挥手1.1 TCP状态1.2四次挥手的过程1.3time_wait等待1.4三次四次的总结 2.前段时间总结3.滑动窗口---传输效率机制3.1原理分析3.2丢包的处理3.3快速重传 4.流量控制---接收方安全机制4.1流量控制思路4.2剩余空间大小4.3探测包的机制 5.拥塞控制---考虑…

单细胞数据分析(一):10X数据生成seurat数据对象

文章目录 介绍加载R包数据链接导入数据过滤细胞:移除双重细胞合并所有seurat数据对象输出结果系统信息介绍 在单细胞基因组学研究中,Seurat是一个流行的R包,用于单细胞基因表达数据的分析和探索。以下是如何从10X基因注释数据生成Seurat数据对象,并对该数据进行过滤的步骤…

了解SQLExpress数据库

SQLExpress&#xff08;Microsoft SQL Server Express&#xff09;是由微软公司开发的一款免费且轻量级的数据库管理系统。以下是关于SQLExpress的详细解释&#xff1a; 一、定义与特点 定义&#xff1a; SQLExpress是Microsoft SQL Server的一个缩减版或基础版&#xff0c;旨在…

C++ 魔法三钥:解锁高效编程的封装、继承与多态

快来参与讨论&#x1f4ac;&#xff0c;点赞&#x1f44d;、收藏⭐、分享&#x1f4e4;&#xff0c;共创活力社区。 目录 &#x1f4af;前言 &#x1f4af;封装 1.封装概念 2.封装格式 3.封装的原理 4.封装的作用 &#x1f4af;继承 1.继承的概念 2.继承格式 3.继承的…

开源 AI 智能名片 2 + 1 链动模式 S2B2C 商城小程序中积分使用价值的拓展策略

摘要&#xff1a;本文围绕开源 AI 智能名片 2 1 链动模式 S2B2C 商城小程序&#xff0c;深入探讨其积分使用价值的丰富策略。详细分析积分兑换礼品、会员升级、积分抵现等方式在该特定商城小程序环境下的应用特点、存在问题及对用户和商城的影响&#xff0c;旨在为商城的优化运…

UE4安卓Gradle工程中的libUE4.so的生成原理

流程图 流程图放在最前面&#xff0c;下面是讲解。 libUE4.so 问&#xff1a;在UE4安卓开发中&#xff0c;libUE4.so即是符号表&#xff0c;又是引擎代码native&#xff0c;是吗&#xff1f; 答&#xff1a;是的&#xff0c;libUE4.so在UE4安卓开发中既包含符号表&#xff0c;…

Java线程池的核心内容详解

文章内容已经收录在《面试进阶之路》&#xff0c;从原理出发&#xff0c;直击面试难点&#xff0c;实现更高维度的降维打击&#xff01; 目录 文章目录 目录Java线程池的核心内容详解线程池的优势什么场景下要用到线程池呢&#xff1f;线程池中重要的参数【掌握】新加入一个任…

Pandas DataFrame学习

1.DataFrame定义 DataFrame 是 Pandas 中的另一个核心数据结构&#xff0c;用于表示二维表格型数据。DataFrame 是一个表格型的数据结构&#xff0c;它含有一组有序的列&#xff0c;每列可以是不同的值类型&#xff08;数值、字符串、布尔型值&#xff09;。DataFrame 既有行索…