62. UE5 RPG 近战攻击获取敌人并造成伤害

在上一篇,我们实现了通过AI行为树控制战士敌人靠近攻击目标触发近战攻击技能,并在蒙太奇动画中触发事件激活攻击的那一刻的伤害判断,在攻击时,我们绘制了一个测试球体,用于伤害范围。
在之前实现的火球术中,我们实现的是一个单体伤害技能,在近战中,我们想实现对范围内的敌人判断,并造成伤害。这也是RPG游戏的通常做法。
所以,我们将在这篇中,实现角色的死亡逻辑,然后接着实现一个函数去获取一定范围内的敌人并造成伤害。

实现死亡逻辑

在敌人接口这里,我们增加两个函数,一个用于判断角色是否死亡,另一个获取角色的Avatar,它们都被设置了BlueprintNativeEvent,它会通过蓝图初始化虚函数,并且可以在蓝图中覆写(如果在蓝图中覆写,C++版本的实现将会失效)

	UFUNCTION(BlueprintNativeEvent, BlueprintCallable)
	bool IsDead() const; //获取当前角色是否死亡

	UFUNCTION(BlueprintNativeEvent, BlueprintCallable)
	AActor* GetAvatar(); //获取当前角色

由于每个角色都需要此功能,我们将在角色基类上面去修改它,首先覆盖它们的父类函数

	/* ICombatInterface战斗接口 */
	virtual UAnimMontage* GetHitReactMontage_Implementation() override;
	virtual FVector GetCombatSocketLocation_Implementation() const override;
	virtual bool IsDead_Implementation() const override;
	virtual AActor* GetAvatar_Implementation() override;
	virtual void Die() override;
	/* ICombatInterface战斗接口 结束 */

创建一个变量,来记录当前是否死亡

protected:
	// Called when the game starts or when spawned
	virtual void BeginPlay() override;

	bool bDead = false; //当前角色死亡状态

实现前面创建的两个函数

bool ARPGCharacter::IsDead_Implementation() const
{
	return bDead;
}

AActor* ARPGCharacter::GetAvatar_Implementation()
{
	return this;
}

我们现在能获取了,还需要一个设置死亡的地方,我们在实现角色死亡这里实现了一个死亡函数,它在内部调用触发每个客户端都会运行此函数,我们可以把设置逻辑写到此函数中。
在这里插入图片描述
在函数底部增加设置死亡的变量
在这里插入图片描述

实现获取范围内的敌人函数

我们现在需要实现一个函数来获取一定范围内的敌人。所以,在我们函数库增加一个新的函数用于获取。
要实现这个功能,我们可以查找以下引擎的库里面是否包含此类型的函数,稍微修改一下,在GameplayStatics文件中,有个名为ApplyRadialDamageWithFalloff函数,它和我们所需的类型差不多,创建一个球的配置项,然后忽略掉一些Actor,然后进行查询,获取到对应的Actors,跟我们所需的效果一致,我们只需要返回即可。
在这里插入图片描述
我们创建一个蓝图库函数,可以通过此函数获取到所有攻击位置的Actor

	//获取到攻击位置半径内的所有动态Actor
	UFUNCTION(BlueprintCallable, Category="MyAbilitySystemLibrary|GameplayMechanics")
	static void GetLivePlayersWithinRadius(const UObject* WorldContextObject, TArray<AActor*>& OutOverlappingActors, const TArray<AActor*>& ActorsToIgnore, float Radius, const FVector& SphereOrigin);

在实现这里,仿造官方库的写法,获取到所有与设置的碰撞体碰撞的数组,然后对数据遍历,将所需的对象返回

void URPGAbilitySystemBlueprintLibrary::GetLivePlayersWithinRadius(const UObject* WorldContextObject,
	TArray<AActor*>& OutOverlappingActors, const TArray<AActor*>& ActorsToIgnore, float Radius,
	const FVector& SphereOrigin)
{
	FCollisionQueryParams SphereParams; //创建一个碰撞查询的配置
	SphereParams.AddIgnoredActors(ActorsToIgnore); //添加忽略的Actor
	
	TArray<FOverlapResult> Overlaps; //创建存储检索到的与碰撞体产生碰撞的Actor
	if (UWorld* World = GEngine->GetWorldFromContextObject(WorldContextObject, EGetWorldErrorMode::LogAndReturnNull)) //获取当前所处的场景,如果获取失败,将打印并返回Null
	{
		//获取到所有与此球体碰撞的动态物体
		World->OverlapMultiByObjectType(Overlaps, SphereOrigin, FQuat::Identity, FCollisionObjectQueryParams(FCollisionObjectQueryParams::InitType::AllDynamicObjects), FCollisionShape::MakeSphere(Radius), SphereParams);
		for(FOverlapResult& Overlap : Overlaps) //遍历所有获取到的动态Actor
		{
			//判断当前Actor是否包含战斗接口   Overlap.GetActor() 从碰撞检测结果中获取到碰撞的Actor
			const bool ImplementsCombatInterface =  Overlap.GetActor()->Implements<UCombatInterface>();
			//判断当前Actor是否存活,如果不包含战斗接口,将不会判断存活(放置的火堆也属于动态Actor,这样保证不会报错)
			if(ImplementsCombatInterface && !ICombatInterface::Execute_IsDead(Overlap.GetActor())) 
			{
				OutOverlappingActors.AddUnique(Overlap.GetActor()); //将Actor添加到返回数组,AddUnique 只有在此Actor未被添加时,才可以添加到数组
			}
		}
	}
}

接着我们在技能类里面,调用创建的此函数,中心设置为在角色上面设置的攻击位置,将自身传入忽略的数组,设置好半径,然后将返回的数组遍历,绘制测试图形,记得在遍历结束后,结束此技能。
在这里插入图片描述
接着查看攻击效果,可以看出,攻击时,不但可以在玩家角色身上绘制测试图形,也可以在敌人身上绘制。
在这里插入图片描述

应用GE

现在我们能够获得到需要造成伤害的Actor,那么接下来,我们将实现伤害的应用。按照我们之前的经验 ,我们需要一个GameplayEffect去对攻击目标造成伤害,在前面的章节49. UE5 RPG 使用Execution Calculations处理对目标造成的最终伤害我们实现了一个造成伤害的GE。并且在54. UE5 RPG 增加伤害类型 增加了技能可以造成多种属性的伤害,我们可以给近战攻击技能直接使用这个GE。
我们需要做的就是创建GE的实例,然后使用SetByCaller将技能的伤害数值传递给GE的实例,接下来,我们将在技能蓝图中通过连连看实现此功能,然后在c++中实现我们实际需要使用的函数。

首先,我们先配置技能的造成伤害的GE,并设置当前技能造成的伤害,我们这里设置的造成物理伤害,并且我们需要在曲线表格中新增加一条伤害曲线使用。
在这里插入图片描述
伤害我们设置了从1级到40级的伤害
在这里插入图片描述
完成了准备工作,接下来,我们就可以修改蓝图的逻辑,在获取到攻击目标后,我们遍历攻击目标数组,从伤害类型中,获取到所有的Keys,然后遍历获取到对应的Value(在蓝图无法直接遍历),我这个现在写的还有问题,就是给每个类型的伤害创建的一个Spec,如果只设置了一种类型的伤害,那么效果是一致的。这里主要也是给展示一下如何实现。
在这里插入图片描述
根据等级获取技能伤害节点是通过代码实现的节点,卸载蓝图函数库中
在这里插入图片描述
那么接下来,我们在C++中实现这个逻辑,这样在蓝图中只需要调用一个方法即可。
我们在RPGDamageGameplayAbility.h类里面增加一个函数,用于给目标应用伤害

	UFUNCTION(BlueprintCallable)
	void CauseDamage(AActor* TargetActor);

在cpp文件中实现它

void URPGDamageGameplayAbility::CauseDamage(AActor* TargetActor)
{
	//创建GE
	FGameplayEffectSpecHandle DamageSpecHandle = MakeOutgoingGameplayEffectSpec(DamageEffectClass, 1.f);
	//通过SetByCaller设置属性伤害
	for(auto Pair : DamageTypes)
	{
		const float ScaleDamage = Pair.Value.GetValueAtLevel(GetAbilityLevel());
		UAbilitySystemBlueprintLibrary::AssignTagSetByCallerMagnitude(DamageSpecHandle, Pair.Key, ScaleDamage);
	}
	//将GE应用给目标
	GetAbilitySystemComponentFromActorInfo()->ApplyGameplayEffectSpecToTarget(
		*DamageSpecHandle.Data.Get(),
		UAbilitySystemBlueprintLibrary::GetAbilitySystemComponent(TargetActor));
}

编译打开UE,在蓝图中修改成我们创建的节点,针对每个目标调用一次函数即可。
在这里插入图片描述

处理玩家角色被敌人攻击不显示伤害数字的问题

我们在被敌人攻击后,无法在角色身上显示伤害的数字,我们去查看一下在AttributeSet里面如何创建的伤害数字的显示。
在显示伤害数字函数中,我们是通过获取到角色的PlayerController,然后通过调用PlayerController身上的函数来实现的。如果是敌人攻击玩家角色,我们是无法在敌人身上获取到PlayerController的。
在这里插入图片描述
所以这里的修改可以修改为,如果从SourceCharacter无法获取到PlayerController,那么我们判断一下目标角色身上获取,然后从目标角色身上获取PlayerController进行调用显示,这样,和这次技能有关的角色都会显示对应的伤害。

void URPGAttributeSet::ShowFloatingText(const FEffectProperties& Props, const float Damage, bool IsBlockedHit, bool IsCriticalHit)
{
	//调用显示伤害数字
	if(Props.SourceCharacter != Props.TargetCharacter)
	{
		//从技能释放者身上获取PC并显示伤害数字
		if(ARPGPlayerController* PC = Cast<ARPGPlayerController>(Props.SourceCharacter->Controller))
		{
			PC->ShowDamageNumber(Damage, Props.TargetCharacter, IsBlockedHit, IsCriticalHit); //调用显示伤害数字
		}
		//从目标身上获取PC并显示伤害数字
		if(ARPGPlayerController* PC = Cast<ARPGPlayerController>(Props.TargetCharacter->Controller))
		{
			PC->ShowDamageNumber(Damage, Props.TargetCharacter, IsBlockedHit, IsCriticalHit); //调用显示伤害数字
		}
	}
}

接着运行查看效果。
在这里插入图片描述

处理多人模式下的问题

我们将运行模式修改,数量修改为两人
在这里插入图片描述
运行起来后,发现敌人被攻击后,会报错,原因是因为AIController为null
在这里插入图片描述
我们加个条件判断即可,判断AIController和黑板组件有没有被设置,如果存在才可以调用。

void ARPGEnemy::HitReactTagChanged(const FGameplayTag CallbackTag, int32 NewCount)
{
	bHitReacting = NewCount > 0;
	GetCharacterMovement()->MaxWalkSpeed = bHitReacting ? 0.f : BaseWalkSpeed;
	//设置黑板键的值
	if(RPGAIController && RPGAIController->GetBlackboardComponent())
	{
		RPGAIController->GetBlackboardComponent()->SetValueAsBool(FName("HitReacting"), bHitReacting);
	}
	// GEngine->AddOnScreenDebugMessage(-1, 1.f, FColor::Green, FString::Printf(TEXT("Hit React bool: %i"), bHitReacting));
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

韩国GreenChip电容式触摸芯片-打造智能触控新时代

在如今科技迅猛发展的时代&#xff1b;智能触控技术已经成为现代生活中不可或缺的一部分&#xff1b;作为一家领先的触控芯片制造商&#xff0c;韩国GreenChip推出的电容式触摸芯片正以其卓越的性能和创新的设计&#xff0c;引领着智能触控的新时代。 韩国GreenChip电容式触摸…

嘴尚绝卤味:口感独特,让你一尝难忘的美食新体验!

在美食的世界里&#xff0c;卤味以其独特的口味和制作工艺&#xff0c;一直受到广大食客的喜爱。而在众多的卤味品牌中&#xff0c;嘴尚绝卤味凭借其口感独特、品质卓越的特点&#xff0c;脱颖而出&#xff0c;成为众多美食爱好者的首选。 嘴尚绝卤味&#xff0c;顾名思义&…

ARM公司发展历程

Arm从1990年成立前开始&#xff0c;历经漫长岁月树立各项公司里程碑及产品成就&#xff0c;一步步成为全球最普及的运算平台。 添加图片注释&#xff0c;不超过 140 字&#xff08;可选&#xff09; Acorn 时期 1978年&#xff0c;Chris Curry和Hermann Hauser共同创立了Acorn…

QT 音乐播放器【一】 显示音频级别指示器

文章目录 效果图概述代码总结 效果图 概述 QMediaPlayer就不介绍了&#xff0c;就提供了一个用于播放音频和视频的媒体播放器 QAudioProbe 它提供了一个探针&#xff0c;用于监控音频流。当音频流被捕获或播放时&#xff0c;QAudioProbe 可以接收到音频数据。这个类在需要访问…

python下绘制地形晕染(shading)图

python可以利用rasterio&#xff0c;cartopy&#xff0c;matplotlib等库绘制地形晕染图。 1.获取高程数据 高程数据可以从GEBCO网站下载&#xff1a;&#xff08;https://www.gebco.net/data_and_products/gridded_bathymetry_data/&#xff09;。 选择raster&#xff08;栅…

flask 之JWT认证实现

目录 1、JWT 1.1、JWT概述 1.2、token的生成 1.3、token校验 1.4、flask项目中实现JWT认证 1、JWT 1.1、JWT概述 JWT&#xff08;JSON Web Token&#xff09;是一种用于身份验证和授权的开放标准。它由三部分组成&#xff0c;分别是头部、负载和签名。 头部&#xff0…

24、Linux网络端口

Linux网络端口 1、查看网络接口信息ifconfig ens33 eth0 文件 ifconfig 当前设备正在工作的网卡&#xff0c;启动的设备。 ifconfig -a 查看所有的网络设备。 ifconfig ens33 查看指定网卡设备。 ifconfig ens33 up/down 对指定网卡设备进行开关 基于物理网卡设备虚拟的…

搭建 3D 智慧农场可视化

运用图扑自主研发的 HT 产品&#xff0c;全程零代码搭建 3D 轻量化 Low Poly 风格的智慧农场可视化解决方案&#xff0c;无缝融合 2D、3D 技术&#xff0c;1&#xff1a;1 还原农场的区域规划&#xff0c;展开对农作物间的网格化管理。

真国色码上赞,科技流量双剑合璧,商家获客新纪元开启

在数字化浪潮汹涌的今天,真国色研发团队依托红玉房网络科技公司的雄厚实力,凭借科技领先的核心竞争力,推出了创新性的商家曝光引流工具——码上赞。这款工具借助微信支付与视频号已有功能,为实体商家提供了一种全新的引流获客方式,实现了科技与商业的完美融合。 科技领先,流量黑…

MATLAB format

在MATLAB中&#xff0c;format 是一个函数&#xff0c;用于控制命令窗口中数值的显示格式。这个函数可以设置数值的精度、显示的位数等。以下是一些常用的 format 命令&#xff1a; format long&#xff1a;以默认的长格式显示数值&#xff0c;通常显示15位有效数字。format s…

图像处理之基于标记的分水岭算法(C++)

图像处理之基于标记的分水岭算法&#xff08;C&#xff09; 文章目录 图像处理之基于标记的分水岭算法&#xff08;C&#xff09;前言一、基于标记点的分水岭算法应用1.实现步骤&#xff1a;2.代码实现 总结 前言 传统分水岭算法存在过分割的不足&#xff0c;OpenCV提供了一种…

CTFHUB-密码口令-弱口令

目录 题干介绍 密码字典 找flag过程 尾声 题干介绍 通常认为容易被别人&#xff08;他们有可能对你很了解&#xff09;猜测到或被破解工具破解的口令均为弱口令。 密码字典 下载地址&#xff1a;GitHub - NepoloHebo/Commonly-used-weak-password-dictionary: 常用弱密码字…

川北医学院与爱尔眼科医院集团签署战略合作协议共谋医学发展新篇章

为深入贯彻落实党的二十大精神&#xff0c;统筹校、企、医、政多方资源&#xff0c;服务“健康中国”战略&#xff0c;推动眼健康产业发展&#xff0c;打造国家及区域级眼科医学中心&#xff0c;2024年5月31日&#xff0c;川北医学院与爱尔眼科医院集团在成都举行战略合作协议签…

腾讯云 TDMQ for Apache Pulsar 多地区高可用容灾实践

作者介绍 林宇强 腾讯云高级工程师 专注于消息队列、API网关、微服务、数据同步等 PaaS 领域。有多年的开发和维护经验&#xff0c;目前在腾讯云从事 TDMQ Pulsar 商业化产品方向的研发工作。 导语 本文将从四个维度&#xff0c;深入剖析 Pulsar 在多可用区高可用领域的容…

单实例11.2.0.4迁移到11.2.0.4RAC_使用rman异机恢复

保命法则&#xff1a;先备份再操作&#xff0c;磁盘空间紧张无法备份就让满足&#xff0c;给自己留退路。 场景说明&#xff1a; 1.本文档的环境为同平台、不同版本&#xff08;操作系统版本可以不同&#xff0c;数据库版本相同&#xff09;&#xff0c;源机器和目标机器部分…

QML信号连接到c++的槽函数(五)

文章目录 前言一、QML Signal and Handler Event System二、QML信号连接到c++的槽函数代码实例1. 创建一个QML 工程2. 用C++ 实现一个QML Types3. 代码实例4. 运行结果总结参考资料前言 本文主要介绍,如何将QML 中的信号连接到C++ 中的槽函数 软硬件环境: 硬件:PC 软件:wi…

MDK5.10 安装手册

1.MDK5.10 安装 打开开发板光盘&#xff1a; 6 &#xff0c;软件资料 \ 软件 \MDK5 &#xff0c;双击 mdk_510.exe &#xff0c;进行安装。这里我们 将其安装到 D 盘&#xff0c; MDK5.10 文件夹下&#xff0c;需要设置安装路径&#xff0c;如图 1.1 所示&#xff1a; …

上传图片并显示#Vue3#后端接口数据

上传图片并显示#Vue3#后端接口数据 效果&#xff1a; 上传并显示图片 代码&#xff1a; <!-- 上传图片并显示 --> <template><!-- 上传图片start --><div><el-form><el-form-item><el-uploadmultipleclass"avatar-uploader&quo…

独立游戏开发的 6 个步骤

&#x1f482; 个人网站:【 摸鱼游戏】【神级代码资源网站】【工具大全】&#x1f91f; 一站式轻松构建小程序、Web网站、移动应用&#xff1a;&#x1f449;注册地址&#x1f91f; 基于Web端打造的&#xff1a;&#x1f449;轻量化工具创作平台&#x1f485; 想寻找共同学习交…

计算机网络⑩ —— Linux系统如何收发网络包

转载于小林coding&#xff1a;https://www.xiaolincoding.com/network/1_base/how_os_deal_network_package.html 1. OSI七层模型 应用层&#xff0c;负责给应用程序提供统一的接口&#xff1b;表示层&#xff0c;负责把数据转换成兼容另一个系统能识别的格式&#xff1b;会话…