61. UE5 RPG 实现敌人近战攻击技能和转向攻击

news2024/11/19 21:23:13

在前面,我们实现了敌人的AI系统,敌人可以根据自身的职业进行匹配对应的攻击方式。比如近战战士会靠近目标后进行攻击然后躲避目标的攻击接着进行攻击。我们实现了敌人的AI行为,但是现在还没有实现需要释放的技能,接下来,我们将实现敌人的使用的技能,刚好回顾一下之前的实现的功能。

首先基于之前的伤害技能基类,创建一个近战技能基类
在这里插入图片描述
命名为近战技能 RPGMeleeAbility
在这里插入图片描述
我们要实现技能的激活,需要使用到GameplayTag,所以我们增加一个新的技能标签用于激活。
在RPGGameplayTags.h增加新的标签

FGameplayTag Abilities_Attack; //攻击技能激活标签

然后将标签添加到标签管理器

	/*
	 * Abilities
	 */
	
	GameplayTags.Abilities_Attack = UGameplayTagsManager::Get()
		.AddNativeGameplayTag(
			FName("Abilities.Attack"),
			FString("攻击技能标签")
		);

接下来,我们要实现在角色数据表里面配置它的技能,打开Character Class Info.h增加对应的属性设置

//对应每个职业的属性和技能
USTRUCT()
struct FCharacterClassDefaultInfo
{
	GENERATED_BODY()

	UPROPERTY(EditDefaultsOnly, Category="Class Defaults")
	TSubclassOf<UGameplayEffect> PrimaryAttributes;

	UPROPERTY(EditDefaultsOnly, Category="Class Defaults")
	TArray<TSubclassOf<UGameplayAbility>> StartupAbilities;
};

后面在UE的蓝图里面设置以后,我们可以在结构体内获取需要应用的技能。接下来,我们还需要回忆一下如何应用敌人的技能的,我们是在敌人的基类里面,去实现的技能的应用,
在这里插入图片描述
我们要扩展这个函数,增加传入角色的类型,通过类型去获取特定职业的技能。

	//初始化角色的技能
	UFUNCTION(BlueprintCallable, Category="MyAbilitySystemLibrary|CharacterClassDefaults")
	static void GiveStartupAbilities(const UObject* WorldContextObject, UAbilitySystemComponent* ASC, ECharacterClass CharacterClass);

扩展函数,从数据结构中获取到数据并应用到角色的ASC上

void URPGAbilitySystemBlueprintLibrary::GiveStartupAbilities(const UObject* WorldContextObject, UAbilitySystemComponent* ASC, ECharacterClass CharacterClass)
{
	//从实例获取到关卡角色的配置
	UCharacterClassInfo* CharacterClassInfo = GetCharacterClassInfo(WorldContextObject);
	if(CharacterClassInfo == nullptr) return;

	//从战斗接口获取到角色的等级
	ICombatInterface* CombatInterface = Cast<ICombatInterface>(ASC->GetAvatarActor());
	int32 CharacterLevel = 1;
	if(CombatInterface)
	{
		CharacterLevel = CombatInterface->GetPlayerLevel();
	}

	//应用角色拥有的技能数组
	for(const TSubclassOf<UGameplayAbility> AbilityClass : CharacterClassInfo->CommonAbilities)
	{
		FGameplayAbilitySpec AbilitySpec = FGameplayAbilitySpec(AbilityClass, CharacterLevel); //创建技能实例
		ASC->GiveAbility(AbilitySpec); //只应用不激活
	}

	//获取到默认的基础角色数据
	const FCharacterClassDefaultInfo ClassDefaultInfo = CharacterClassInfo->GetClassDefaultInfo(CharacterClass);

	//应用职业技能数组
	for(const TSubclassOf<UGameplayAbility> AbilityClass : ClassDefaultInfo.StartupAbilities)
	{
		FGameplayAbilitySpec AbilitySpec = FGameplayAbilitySpec(AbilityClass, CharacterLevel); //创建技能实例
		ASC->GiveAbility(AbilitySpec); //只应用不激活
	}
}

敌人的角色类型也是设置在敌人基类上的,所以我们可以直接调用时传入

	//初始化角色的技能
	if(HasAuthority()){
		URPGAbilitySystemBlueprintLibrary::GiveStartupAbilities(this, AbilitySystemComponent, CharacterClass);
	}

在UE中设置

接着我们可以编译代码打开UE,在UE里面创建一个对应的蓝图类
在这里插入图片描述
命名为GA_GoblinSpearAttack
在这里插入图片描述
首先设置技能标签,我们就可以通过标签激活技能。
在这里插入图片描述
在技能里实现测试代码,在触发技能时,绘制一个绿色的球
在这里插入图片描述
接着打开我们的数据表,现在每个职业多了一个需要设置的技能数组,将我们创建的技能添加给战士
在这里插入图片描述
攻击是由AI触发的,所以,我们在AI的攻击任务中,通过标签激活技能即可。我们从控制的pawn中获取到ASC,然后通过标签激活技能
在这里插入图片描述
创建的变量我们可以将其设置外部可以设置
在这里插入图片描述
然后再行为树中设置激活的技能标签
在这里插入图片描述
接着运行测试效果,如果允许哥布林在攻击时绘制绿色的球,证明我们技能激活成功。
在这里插入图片描述

设置技能攻击蒙太奇

回忆一下之前我们实现的火球术,需要使用一个蒙太奇动画,然后在蒙太奇动画中触发事件发射火球实现技能的释放。接下来,我们使用同样的思路实现近战攻击的技能。
找到敌人的攻击动画,创建一个蒙太奇
在这里插入图片描述
创建名称AM_Attack_GoblinSpear,方便在蒙太奇下拉中选择
在这里插入图片描述
在蒙太奇中,我们需要增加MotionWarping来控制朝向,注意,动画必须要支持根动画
在这里插入图片描述
设置角色在蓄力的时候转向
在这里插入图片描述
设置触发名称,关闭移动,只留下转向,切换转向类型为朝向目标
在这里插入图片描述
我们有了蒙太奇,还需要实现在攻击时朝向攻击目标,按照之前的实现方式,我们通过MotionWarpping插件实现转向。

添加转向插件

我们需要在敌人基类身上增加MotionWarpping插件
在这里插入图片描述
实现调用,和主角的一样即可,其实这里我们可以实现一个角色基类蓝图,在里面设置一些通用的函数,这里先不改。
在这里插入图片描述
要实现这个功能,我们需要让敌人知道攻击目标的位置,然后攻击时朝向它,我们需要在AI控制器中获取到目标。
我们在敌人接口里增加两个函数,用于设置和获取攻击目标,这里设置了BlueprintNativeEvent,它默认给我们实现,并且可以在蓝图中实现此函数,如果在蓝图中实现了此函数,在蓝图中调用,将使用蓝图的版本。

	UFUNCTION(BlueprintCallable, BlueprintNativeEvent)
	void SetCombatTarget(AActor* InCombatTarget); //设置敌人的攻击目标

	UFUNCTION(BlueprintCallable, BlueprintNativeEvent)
	AActor* GetCombatTarget() const; //获取敌人的攻击目标

接下来我们在敌人基类里面覆写这两个函数,并去实现,这样写法是因为我们是通过UE让蓝图去实现的此函数,所以我们需要加上Vitrual和后面的_Implementation

	/* IEnemyInterface敌人接口 */
	virtual void HighlightActor() override; //高亮
	virtual void UnHighlightActor() override; //取消高亮
	virtual AActor* GetCombatTarget_Implementation() const override;
	virtual void SetCombatTarget_Implementation(AActor* InCombatTarget) override;
	/* IEnemyInterface敌人接口 结束 */

在cpp中实现这两个函数,我们也可以在蓝图中实现,这里看个人喜好

AActor* ARPGEnemy::GetCombatTarget_Implementation() const
{
	return CombatTarget;
}

void ARPGEnemy::SetCombatTarget_Implementation(AActor* InCombatTarget)
{
	CombatTarget = InCombatTarget;
}

有了设置攻击目标的函数,我们在AI攻击任务里面就可以设置攻击对象了。
在任务里增加一个黑板键选择器,用于在AI行为树中设置绑定的黑板键
在这里插入图片描述
在AI行为树中设置攻击目标为跟随目标黑板键
在这里插入图片描述
这样我们就可以在任务里面获取攻击目标,并设置给控制的Pawn身上
在这里插入图片描述
接下来,我们在技能里面,从角色身上获取到攻击目标,然后转换为战斗接口,调用偏转朝向的函数,将朝向位置设置,然后再调用蒙太奇播放动画
在这里插入图片描述
接着允许查看效果,是否真的能捅向目标
在这里插入图片描述

添加攻击事件

接下来,我们需要在蒙太奇动画里,攻击的那一刻,触发一个事件,来告诉技能当前可以计算攻击。就像之前实现火球术时的一样。
在这里插入图片描述
由于我们没有设置对应的通知,我们去标签管理器增加一个近战攻击的通知标签。由于这个标签不需要在c++内使用,所以我们可以直接通过UE添加。
在这里插入图片描述
设置属于攻击的近战攻击标签
在这里插入图片描述
设置完成,打开蒙太奇,设置到通知上面,这样就可以在技能里面去接收对应的标签通知了。
在这里插入图片描述
然后我们在技能中设置等待游戏事件即可,Only Match Exact是标签必须全部匹配才可以触发事件
在这里插入图片描述
现在我们接收到事件了,还需要考虑如何触发攻击。在之前实现火球从法杖杖尖处释放时,我们在战斗接口设置了一个获取技能释放位置的函数,所以我们可以通过获取到设置的位置,生成一个碰撞球体,判断是否和目标产生重叠实现攻击并应用GE。
在这里插入图片描述
但是当前函数无法在蓝图中调用,所以,我们需要修改它,将其变成可以在蓝图中调用的版本

	//获取技能释放位置,通过在蓝图中设置获取WeaponTipSocketName的位置
	UFUNCTION(BlueprintNativeEvent, BlueprintCallable)
	FVector GetCombatSocketLocation() const;

并将cpp的实现删除。

在角色基类修改它的继承,修改成GetCombatSocketLocation_Implementation

virtual FVector GetCombatSocketLocation_Implementation() const override;

并将实现代码函数名称也修改掉

FVector ARPGCharacter::GetCombatSocketLocation_Implementation() const
{
	return Weapon->GetSocketLocation(WeaponTipSocketName);
}

完成以后,就可以编译打开UE,并设置它的WeaponTipSocketName
在这里插入图片描述
这里名称,我们可以在武器骨骼上面增加插槽实现
在这里插入图片描述
接着在技能蓝图里,我们首先实现接收到事件后绘制一个调试球体,来表现攻击范围
在这里插入图片描述
运行查看释放能够正确绘制出调试球体
在这里插入图片描述
我们在点击实现角色攻击时,发现一个问题,有个地方报错了,提示我们不要在接口中直接调用Event函数。而是调用Execute_GetCombatSocketLocation。
在这里插入图片描述
往前定位发现是在调用,直接调用获取位置,由于前面我们将其修改成了蓝图编译生成函数,所以在C++里面不能够直接调用
在这里插入图片描述
所以我们修改此行代码为使用Execute_GetCombatSocketLocation调用

const FVector SocketLocation = ICombatInterface::Execute_GetCombatSocketLocation(GetAvatarActorFromActorInfo());

接着运行测试就行了。

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

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

相关文章

提升船舶安全性与效率:隔离驱动芯片的应用

随着科技的不断发展&#xff0c;船舶行业也在不断迎来新的技术革新&#xff0c;其中隔离驱动芯片作为一种关键的电子元件&#xff0c;在船舶领域发挥着重要作用。本文将深入探讨隔离驱动芯片在船舶领域的应用及其技术特点。 隔离驱动芯片提升船舶系统安全性 船舶作为大型交通工…

信息系统项目管理师0604:项目整合管理 — 历年考题(详细分析与讲解)

点击查看专栏目录 1、2017年11月第34题 项目经理张工带领团队编制项目管理计划,(34)不属于编制项目管理计划过程的依据。 A. 项目章程B. 事业环境因素C. 组织过程资产D. 工作分解结构【答案】D 【解析】考查的是编写项目管理计划的相关知识,需要掌握。编写项目管理计划的…

Kafka broker的新增和剔除(服役与退役)

说明&#xff1a;集群现有broker:node1,node2,node3三个,broker.id分别为0&#xff0c;1&#xff0c;2 已有两个topic&#xff1a;products、cities 1、退役&#xff08;Kafka集群中减少一个服务器broker2&#xff09; 退役后要保证剩下的服务器数量大于等于备份数&#xff0c…

自适应全屏滚动,实现swiper 全屏滚动效果与解决bug

原来是想复刻明日方舟的滚动代码&#xff0c;基于此进行开发 js实现网页全屏切换&#xff08;平滑过渡&#xff09;&#xff0c;鼠标滚动切换_网页滚动条下滑和全屏切换是什么-CSDN博客 但是发现bug BUG 原因是只获取了一次高度 于是增加窗口监听&#xff0c; 但是发现拉伸…

Python | Leetcode Python题解之第123题买卖股票的最佳时机III

题目&#xff1a; 题解&#xff1a; class Solution:def maxProfit(self, prices: List[int]) -> int:n len(prices)buy1 buy2 -prices[0]sell1 sell2 0for i in range(1, n):buy1 max(buy1, -prices[i])sell1 max(sell1, buy1 prices[i])buy2 max(buy2, sell1 - …

从一个netty程序说一说TCP三次握手的总结及参数优化

一、背景 TCP连接经历了三次握手&#xff0c;当我们开发一个netty程序&#xff0c;运行在线上环境后&#xff0c;如何对其进行监控&#xff0c;并适时地进行参数调优。 本文以我们生产环境的一个通道程序&#xff0c;看一看三次握手的过程&#xff0c;以及Linux系统关于创建h…

翻译《The Old New Thing》- What a drag: Dragging a virtual file (IStream edition)

What a drag: Dragging a virtual file (IStream edition) - The Old New Thing (microsoft.com)https://devblogs.microsoft.com/oldnewthing/20080319-00/?p23073 Raymond Chen 2008年03月19日 拖拽虚拟文件&#xff08;IStream 版本&#xff09; 上一次&#xff0c;我们看…

Spring Cloud | 客户端 “负载均衡器“ : Ribbon

目录: 1. 什么是 "负载均衡" ? ( 通过 "负载均衡" 可以将 "用户请求" "分发" 到 不同的服务器&#xff0c;以此来提高 "性能" 和 "可靠性" )2. "负载均衡" 的 分类 &#xff1f;3. 认识 Ribbon :3.1 R…

Vitis HLS 学习笔记--控制驱动与数据驱动混合编程

目录 1. 简介 2. 示例分析 2.1 代码分析 2.2 控制驱动TLP的关键特征 2.3 数据驱动TLP的关键特征 3. 总结 1. 简介 在 HLS 硬件加速领域&#xff0c;Vitis HLS 提供了强大的抽象并行编程模型。这些模型包括控制驱动和数据驱动的任务级并行性&#xff08;TLP&#xff09;&…

【网络安全的神秘世界】MySQL

&#x1f31d;博客主页&#xff1a;泥菩萨 &#x1f496;专栏&#xff1a;Linux探索之旅 | 网络安全的神秘世界 | 专接本 MySQL MySQL 教程 | 菜鸟教程 (runoob.com) 什么是数据库 数据库&#xff08;Database&#xff09;是按照数据结构来组织、存储和管理数据的仓库 在do…

Mac OS 用户开启 80 端口

开启端口 sudo vim /etc/pf.conf # 开放对应端口 pass out proto tcp from any to any port 8080 # 刷新配置文件 sudo pfctl -f /etc/pf.conf sudo pfctl -e获取本机ip地址 ifconfig en0 | grep inet | grep -v inet6 | awk {print $2}访问指定端口

Pytorch反向传播算法(Back Propagation)

一&#xff1a;revise 我们在最开始提出一个线性模型。 x为我们的输入&#xff0c;w为权重。相乘的结果是我们对y的预测值。 那我们在训练时就是对这个权重w进行更新&#xff0c;就需要用到上一章提到的梯度下降算法&#xff0c;不断更新w。但是此时注意不是用y的预测值对w进…

go解析yaml

go解析yaml文件关键就是结构体的创建 初学go tag字段要和yaml文件中的key对应起来&#xff0c;每个层级都要创建对应的结构体&#xff0c;有点烦 package configimport ("gopkg.in/yaml.v3""os" )type Config struct {MysqlConfig MysqlConfig yaml:&q…

生成树协议STP(Spanning Tree Protocol)

为了提高网络可靠性&#xff0c;交换网络中通常会使用冗余链路。然而&#xff0c;冗余链路会给交换网络带来环路风险&#xff0c;并导致广播风暴以及MAC地址表不稳定等问题&#xff0c;进而会影响到用户的通信质量。生成树协议STP&#xff08;Spanning Tree Protocol&#xff0…

段码屏|液晶显示模块|超低功耗LCD驱动芯片

1 简介 PC164S32 是一款支持 128 点 (32 4)显示 的多功能 LCD 控制器芯片&#xff0c;内部存储器RAM数据直接映射到 LCD 显示。可软件配置特性使其适用于包括 LCD 模块和显示子系统在内的多种 LCD 应用。主控制器与 PC164S32接口仅需3 或 4 条线。内置的省电模式极大的降低了功…

第 11 章 排序

第 11 章 排序 Abstract 排序犹如一把将混乱变为秩序的魔法钥匙&#xff0c;使我们能以更高效的方式理解与处理数据。 无论是简单的升序&#xff0c;还是复杂的分类排列&#xff0c;排序都向我们展示了数据的和谐美感。 本章内容 11.1 排序算法11.2 选择排序11.3 冒…

ThinkPHP5发送邮件如何配置?有哪些技巧?

ThinkPHP5发送邮件的性能怎么优化&#xff1f;批量发信的方法&#xff1f; 邮件发送功能是许多应用程序的关键组成部分&#xff0c;尤其是在用户注册、密码重置和通知等功能中尤为重要。AokSend将详细介绍如何在thinkphp5中配置和使用邮件发送功能&#xff0c;并确保你可以轻松…

C语言王国——杨氏矩阵

目录 1. 引言 2. 了解杨氏矩阵 3. 思路分析 4. 代码 5. 总结 1. 引言 最近在做二维数组的训练的时候发现了一个很有意思的题&#xff1a; 一看这不是杨氏矩阵嘛&#xff0c;接下来就由姜糖我带大家了解一下这个著名的矩阵。 2. 了解杨氏矩阵 通过查阅百度得知&#xff1a; …

HNU-深度学习-电商多模态图文检索

前言 主要是跟着baseline搭了一遍&#xff0c;没有想到很好的优化。 有官方教程&#xff0c;但是有点谬误&#xff0c;所以就想着自己记录一下我的完成过程。 github项目地址&#xff1a; https://github.com/OFA-Sys/Chinese-CLIP 官方文档&#xff1a; 电商多模态图文检…

可用于嵌入式的解释器调研对比,及lua解释器介绍

嵌入式不一定只能用C! ---------------------------------------------------------------------------------------手动分割线-------------------------------------------------------------------------------- 本文章参考了以下文章&#xff1a; 这里是引用 ------------…