57. UE5 RPG 处理AI敌人转向以及拾取物品的问题

在上一篇文章中,我们实现了使用AI行为树控制敌人进行移动,它们可以一直跟随玩家,虽然现在还未实现攻击。但在移动过程中,我发现了有两个问题,第一个是敌人转向的时候很僵硬,可以说是瞬间转向的,这个原因是角色默认是使用控制器切换朝向造成的。第二个问题是敌人现在也可以拾取药瓶喝药,这个不能忍,造成这个原因是因为药瓶是碰撞触发的,没有对拾取的目标进行一个类型区分。
在这一篇中,我们主要将这两个问题解决一下,然后再继续进行敌人的AI行为树的制作。

处理敌人转向问题

敌人的转向问题很好解决,我们之前就处理过角色身上的转向问题,首先就是先将角色身上的使用控制器控制Yaw给关闭。
在蓝图中,我们可以将 使用控制器旋转Yaw 选项关闭
然后开启 将旋转朝向运动 (角色会朝向运动的方向)
在这里插入图片描述
我们将在c++里面设置,将这个配置写死,保证以后所有的敌人都使用这个配置。
打开敌人基类,在 构造函数中增加以下代码,会有同样的效果

	bUseControllerRotationPitch = false;
	bUseControllerRotationRoll = false;
	bUseControllerRotationYaw = false;
	GetCharacterMovement()->bUseControllerDesiredRotation = true;

这样,就完成了对敌人转向问题的处理。

处理敌人可以拾取的问题

接下来我们处理敌人可以拾取药瓶的问题,比如普通药瓶敌人是无法拾取的,但是火堆的那种,可以实现对敌人的应用,我准备在基类上面增加属性去控制。
首先在基类上面增加属性,这里我额外增加了一个控制销毁的属性,我们之前是在蓝图中实现销毁的,现在,我们将此移动到代码中。

	//Instant和Duration的GE在应用后,此物体是否需要被销毁
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="Apply Effects")
	bool bDestroyOnEffectApplication = true;

	//敌人是否能够拾取此物体
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="Apply Effects")
	bool bApplyEffectsToEnemies = false;

之前我们实现的时候,是在蓝图中实现的,调用代码实现的函数节点,我们也在蓝图中实现应用GE
在这里插入图片描述
接着,我们修改逻辑,实现在应用效果后删除的逻辑,我们将在应用效果后在非无限时间GE后面,判断是否需要在应用后销毁
在这里插入图片描述
然后就是处理是否敌人可拾取的权限,首先我们需要判断当前是否为敌人,然后再判断敌人是否有权限
如果不是敌人 &&后面的逻辑也不会执行,这个判断直接返回false,如果是敌人,并且敌人无法拾取,变量为false,后面也是true,那么将不会执行后面的逻辑。

if(TargetActor->ActorHasTag("Enemy") && !bApplyEffectsToEnemies) return;

我们需要在OnOverlap(触发开始重叠事件)时判断

void ARPGEffectActor::OnOverlap(AActor* TargetActor)
{
	//如果触发角色类型为敌人,并且此拾取物设置无法被敌人拾取
	if(TargetActor->ActorHasTag("Enemy") && !bApplyEffectsToEnemies) return;

针对于一些在OnEndOverlap(结束重叠事件)时也会触发,所以,我们也要在结束时判断

void ARPGEffectActor::OnEndOverlap(AActor* TargetActor)
{
	//如果触发角色类型为敌人,并且此拾取物设置无法被敌人拾取
	if(TargetActor->ActorHasTag("Enemy") && !bApplyEffectsToEnemies) return;

接着编译打开蓝图,我们这些配置项就可以有效的利用起来了
我们可以选择应用什么类型的GE,并在接触时触发还是结束重叠时触发,以及对于无限时间的GE,可以选择在离开时是否清楚GE的效果
在这里插入图片描述
OnOverlap和OnEndOverlap两个函数没有在函数中调用,我们可以按需调用,比如只需要调用OnOverlap函数,我们在蓝图中调用即可
在这里插入图片描述
如果是需要在触发结束重叠时触发,那么我们需要将OnEndOverlay调用,但是对于那种无限时间的GE,并且还需要在结束时清除掉,我们就需要两个方法都调用
在这里插入图片描述

源码

RPGEffectActor.h

// 版权归暮志未晚所有。

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "GameplayEffectTypes.h"
#include "RPGEffectActor.generated.h"

struct FActiveGameplayEffectHandle;
class UAbilitySystemComponent;
class UGameplayEffect;

//效果应用状态枚举
UENUM(BlueprintType) 
enum class EEffectApplicationPolicy
{
	ApplyOnOverlap,
	ApplyOnEndOverlap,
	DoNotApply
};

//效果移除的状态枚举
UENUM(BlueprintType) 
enum class EEffectRemovalPolicy
{
	RemoveOnEndOverlap,
	DoNotRemove
};

/**
 * 在场景中可放置的影响角色属性的物件基类
 */
UCLASS()
class AURA_API ARPGEffectActor : public AActor
{
	GENERATED_BODY()
	
public:	
	ARPGEffectActor();

protected:
	// 游戏开始或生成对象时回调
	virtual void BeginPlay() override;

	//给与目标添加GameplayEffect效果
	UFUNCTION(BlueprintCallable) 
	void ApplyEffectToTarget(AActor* TargetActor, TSubclassOf<UGameplayEffect> GameplayEffectClass);

	//在重叠开始时处理效果的添加删除逻辑
	UFUNCTION(BlueprintCallable) 
	void OnOverlap(AActor* TargetActor);

	//在重叠结束时处理效果的添加删除逻辑
	UFUNCTION(BlueprintCallable) 
	void OnEndOverlap(AActor* TargetActor);

	//Instant和Duration的GE在应用后,此物体是否需要被销毁
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="Apply Effects")
	bool bDestroyOnEffectApplication = true;

	//敌人是否能够拾取此物体
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="Apply Effects")
	bool bApplyEffectsToEnemies = false;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="Apply Effects")
	TSubclassOf<UGameplayEffect> InstantGameplayEffectClass; //生成GameplayEffect的类

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="Apply Effects")
	EEffectApplicationPolicy InstantEffectApplicationPolicy = EEffectApplicationPolicy::DoNotApply;
	
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="Apply Effects")
	TSubclassOf<UGameplayEffect> DurationGameplayEffectClass; //生成具有一定持续时间的GameplayEffect的类

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="Apply Effects")
	EEffectApplicationPolicy DurationEffectApplicationPolicy = EEffectApplicationPolicy::DoNotApply;
	
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="Apply Effects")
	TSubclassOf<UGameplayEffect> InfinityGameplayEffectClass; //生成具有一定持续时间的GameplayEffect的类

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="Apply Effects")
	EEffectApplicationPolicy InfinityEffectApplicationPolicy = EEffectApplicationPolicy::DoNotApply;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="Apply Effects")
	EEffectRemovalPolicy InfinityEffectRemovalPolicy = EEffectRemovalPolicy::RemoveOnEndOverlap;

	//用于存储当前已经激活的GameplayEffect的句柄的map
	TMap<FActiveGameplayEffectHandle, UAbilitySystemComponent*> ActiveEffectHandles;

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="Apply Effects")
	float ActorLevel = 1.f;
};

RPGEffectActor.cpp

// 版权归暮志未晚所有。


#include "Actor/RPGEffectActor.h"
#include "ActiveGameplayEffectHandle.h"
#include "AbilitySystemBlueprintLibrary.h"
#include "AbilitySystemComponent.h"

ARPGEffectActor::ARPGEffectActor()
{
 	// 设置当前对象是否每帧调用Tick()
	PrimaryActorTick.bCanEverTick = false;

	SetRootComponent(CreateDefaultSubobject<USceneComponent>("SceneRoot"));
}


void ARPGEffectActor::BeginPlay()
{
	Super::BeginPlay();
}

void ARPGEffectActor::ApplyEffectToTarget(AActor* TargetActor, TSubclassOf<UGameplayEffect> GameplayEffectClass)
{
	/**
	* 默认自己编写从actor身上获取ASC的方式
	* IAbilitySystemInterface* ASCInterface = Cast<IAbilitySystemInterface>(TargetActor); //判断当前actor是否有技能系统接口
	if(ASCInterface)
	{
		UAbilitySystemComponent* TargetASC = ASCInterface->GetAbilitySystemComponent(); 
	}
	 */

	//获取ASC
	UAbilitySystemComponent* TargetASC = UAbilitySystemBlueprintLibrary::GetAbilitySystemComponent(TargetActor);
	if(TargetASC == nullptr) return;
	
	check(GameplayEffectClass);
	//创建Effect的句柄 包含了实例化Effect所需数据
	FGameplayEffectContextHandle EffectContextHandle = TargetASC->MakeEffectContext();
	//设置创建Effect的对象
	EffectContextHandle.AddSourceObject(this);
	//Effect的实例化后的句柄,可以通过此来寻找调用
	const FGameplayEffectSpecHandle EffectSpecHandle = TargetASC->MakeOutgoingSpec(GameplayEffectClass, ActorLevel, EffectContextHandle);
	//从句柄中获取到实例的地址,并被应用。
	const FActiveGameplayEffectHandle ActiveGameplayEffectHandle = TargetASC->ApplyGameplayEffectSpecToSelf(*EffectSpecHandle.Data.Get());

	//从句柄中获取到定义的对象,并判断设置的
	const bool bIsInfinite = EffectSpecHandle.Data.Get()->Def.Get()->DurationPolicy == EGameplayEffectDurationType::Infinite;
	//在是无限时间效果和需要在结束时清除掉时,将效果句柄添加到map
	if(bIsInfinite && InfinityEffectRemovalPolicy == EEffectRemovalPolicy::RemoveOnEndOverlap)
	{
		ActiveEffectHandles.Add(ActiveGameplayEffectHandle, TargetASC);
	}
	else if(bDestroyOnEffectApplication) //如果设置了应用时删除,除了Infinite的都会自动删除
	{
		Destroy();
	}
}

void ARPGEffectActor::OnOverlap(AActor* TargetActor)
{
	//如果触发角色类型为敌人,并且此拾取物设置无法被敌人拾取
	if(TargetActor->ActorHasTag("Enemy") && !bApplyEffectsToEnemies) return;
	
	if(InstantEffectApplicationPolicy == EEffectApplicationPolicy::ApplyOnOverlap)
	{
		ApplyEffectToTarget(TargetActor, InstantGameplayEffectClass);
	}

	if(DurationEffectApplicationPolicy == EEffectApplicationPolicy::ApplyOnOverlap)
	{
		ApplyEffectToTarget(TargetActor, DurationGameplayEffectClass);
	}

	if(InfinityEffectApplicationPolicy == EEffectApplicationPolicy::ApplyOnOverlap)
	{
		ApplyEffectToTarget(TargetActor, InfinityGameplayEffectClass);
	}
}

void ARPGEffectActor::OnEndOverlap(AActor* TargetActor)
{
	//如果触发角色类型为敌人,并且此拾取物设置无法被敌人拾取
	if(TargetActor->ActorHasTag("Enemy") && !bApplyEffectsToEnemies) return;
	
	//添加效果
	if(InstantEffectApplicationPolicy == EEffectApplicationPolicy::ApplyOnEndOverlap)
	{
		ApplyEffectToTarget(TargetActor, InstantGameplayEffectClass);
	}

	if(DurationEffectApplicationPolicy == EEffectApplicationPolicy::ApplyOnEndOverlap)
	{
		ApplyEffectToTarget(TargetActor, DurationGameplayEffectClass);
	}

	if(InfinityEffectApplicationPolicy == EEffectApplicationPolicy::ApplyOnEndOverlap)
	{
		ApplyEffectToTarget(TargetActor, InfinityGameplayEffectClass);
	}

	//删除效果
	if(InfinityEffectRemovalPolicy == EEffectRemovalPolicy::RemoveOnEndOverlap)
	{
		UAbilitySystemComponent* TargetASC = UAbilitySystemBlueprintLibrary::GetAbilitySystemComponent(TargetActor);
		if(!IsValid(TargetASC)) return;

		//创建存储需要移除的效果句柄存储Key,用于遍历完成后移除效果
		TArray<FActiveGameplayEffectHandle> HandlesToRemove;

		//循环map内存的数据
		for(TTuple<FActiveGameplayEffectHandle, UAbilitySystemComponent*> HandlePair : ActiveEffectHandles)
		{
			//判断是否ASC相同
			if(TargetASC == HandlePair.Value)
			{
				//通过句柄将效果移除,注意,有可能有多层效果,不能将其它层的效果也移除掉,所以只移除一层
				TargetASC->RemoveActiveGameplayEffect(HandlePair.Key, 1);
				//添加到移除列表
				HandlesToRemove.Add(HandlePair.Key);
			}
		}

		//遍历完成后,在Map中将移除效果的KeyValue删除
		for(auto& Handle : HandlesToRemove)
		{
			ActiveEffectHandles.FindAndRemoveChecked(Handle);
		}
	}
}



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

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

相关文章

【kubernetes】多 master 高可用集群架构部署

目录 前言 一、环境部署 二、master02 节点部署 1、拷贝相关文件 2、修改配置文件 3、启动各服务并设置开机自启 4、 查看node节点状态 三、负载均衡部署 1、部署 nginx 服务 1.1 编译安装 nginx 1.2 修改 nginx 配置文件 2、部署 keepalived 服务 2.1 yum安装 ke…

python打包exe,通过文件动态传参运行exe【拿来即用】

配置虚拟环境 安装包&#xff1a;pip install pipenv 创建虚拟环境&#xff1a;创建一个新文件夹&#xff0c;在此目录&#xff0c;打开cmd&#xff0c;输入&#xff1a;pipenv install&#xff0c; 进入虚拟环境&#xff1a;pipenv shell 安装所需的依赖包&#xff1a;pip in…

无人机监测系统:天空之眼,精准掌握地球脉动

在当今信息化快速发展的时代&#xff0c;无人机技术以其独特的优势&#xff0c;正在成为资源调查、环境监测和规划支持的重要工具。无人机监测系统通过搭载多种传感器和设备&#xff0c;能够快速、高效地获取地表信息&#xff0c;为决策提供科学依据。 项目背景 随着全球环境…

VScode解决报错“Remote-SSH XHR failed无法访问远程服务器“的方案

VScode解决报错"Remote-SSH XHR failed无法访问远程服务器"的方案 $ ls ~/.vscode-server/bin 2ccd690cbff1569e4a83d7c43d45101f817401dc稳定版下载链接&#xff1a;https://update.code.visualstudio.com/commit:COMMIT_ID/server-linux-x64/stable 内测版下载链接…

51建模网AR虚拟试用,让网购不再只靠想象!

在数字化的浪潮中&#xff0c;网购已成为现代人生活的一部分。然而&#xff0c;传统的网购模式常常因为无法直接试穿、试用商品&#xff0c;导致买家在收到商品后感到失望&#xff0c;特别是面对大件家居产品时&#xff0c;仅凭屏幕上的图片和尺寸描述&#xff0c;很难准确地把…

阿里云数据库 SelectDB 版全面商业化,开启现代化实时数据仓库的全新篇章

2024 年 5 月 21 日&#xff0c;由阿里云联合飞轮科技共同举办的「阿里云数据库 SelectDB 版商业化产品发布会」于线上召开。阿里巴巴集团副总裁、阿里云数据库产品事业部负责人李飞飞宣布&#xff0c;阿里云数据库 SelectDB 版在中国站及国际站全面发布&#xff0c;正式开启商…

Web应用防火墙的重要性

网络安全是一个永恒的话题&#xff0c;尤其是在未知威胁不断涌现的情况下。企业网络安全是保障业务稳定运行的基础&#xff0c;Web应用防火墙(WAF)是企业网络安全的重要屏障&#xff0c;其性能直接影响到网络服务的质量和安全。 Web应用防火墙是什么&#xff1f; Web应用防火墙…

RS8751XF功能和参数介绍及PDF资料

以下是关于RS8751XF的功能和参数的介绍&#xff1a; 功能描述: 高速、宽带单通道运算放大器 轨到轨输入和输出&#xff0c;确保较大的动态范围 极高的增益带宽乘积&#xff08;GBW&#xff09;&#xff1a;250 MHz&#xff0c;适合高频应用 极高的压摆率&#xff08;SR&#xf…

【UE HTTP】“BlueprintHTTP Server - A Web Server for Unreal Engine”插件使用记录

1. 在商城中下载“BlueprintHTTP Server - A Web Server for Unreal Engine”插件 该插件的主要功能有如下3点&#xff1a; &#xff08;1&#xff09;监听客户端请求。 &#xff08;2&#xff09;可以将文件直接从Unreal Engine应用程序提供到Web。 &#xff08;3&#xff…

Vision Mamba论文阅读(主干网络)

这几天被Mamba刷屏了&#xff0c;又由于本人是做视觉方面任务的&#xff0c;固来看看mamba在视觉上的应用。 今天分享的是Vision Mamba: Vision Mamba: Efficient Visual Representation Learning with Bidirectional State Space Model 论文网址&#xff1a;https://arxiv.or…

【蓝桥杯】

题目列表 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) #include<bits/stdc.h> using llunsigned long long; #define int ll const int N2e510; int k0; std::string s; int a,b,c,d; void solve() {char op;std::cin>>op;if(opA){std::string s;for(int i1;i&l…

vue3结合element-plus之如何优雅的使用表格

背景 表格组件的使用在后台管理系统中是非常常见的,但是如果每次使用表格我们都去一次一次地从 element-plus 官网去 复制、粘贴和修改成自己想要的表格。 这样一来也说得过去,但是如果我们静下来细想不难发现,表格的使用都是大同小异的,每次都去复制粘贴,对于有很多表格…

5月23日 网络编程day6

1.IO多路复用的原理&#xff1f; 答&#xff1a;将文件描述符放入一个集合中&#xff0c;当集合中有事件产生&#xff0c;移除其他文件描述符&#xff0c;执行剩下的文件描述符所对应的任务&#xff0c;往复循环。 2.实现IO多路复用可以使用哪些函数完成&#xff1f; 答&…

【设计模式】JAVA Design Patterns——Balking(止步模式)

&#x1f50d;目的 止步模式用于防止对象在不完整或不合适的状态下执行某些代码。 &#x1f50d;解释 真实世界例子 洗衣机中有一个开始按钮&#xff0c;用于启动衣物洗涤。当洗衣机处于非活动状态时&#xff0c;按钮将按预期工作&#xff0c;但是如果已经在洗涤&#xff0c;则…

嵌入式科普(18)Ubuntu在移动硬盘的安装和启动

目录 一、概述 二、应用场景 三、移动硬盘安装Ubuntu 3.1 移动硬盘格式化 3.2 VMware安装Ubuntu到移动硬盘 四、电脑BIOS启动移动硬盘Ubuntu 五、从VMware启动移动硬盘Ubuntu 六、问题解决(坑)和思考提问 嵌入式科普(18)Ubuntu在移动硬盘的安装和启动 一、概述 在移动硬…

Python实现天气数据采集

Python实现天气数据采集 一、需求介绍二、完整代码一、需求介绍 本次天气数据采集的需求是获取每日的最高温、最低温、风力、风向、天气状况、AQI指数,如图所示,完整代码附后: 本次采集的目标网址是2345天气网: 上图的URL中,beijing是城市名称的缩写,54511即为城市代码…

【机器学习】前沿探索,如何让前端开发更加搞笑

在当今数字化时代&#xff0c;机器学习的崛起为前端开发带来了巨大的机遇和挑战。随着人工智能和数据科学的不断进步&#xff0c;前端工程师不再局限于传统的界面设计和交互体验&#xff0c;而是开始探索如何将机器学习技术融入到他们的工作中&#xff0c;以创造更加智能、个性…

Video-FocalNets: Spatio-Temporal Focal Modulation for Video Action Recognition

标题&#xff1a;Video-FocalNets&#xff1a;用于视频动作识别的时空聚焦调制 源文链接&#xff1a;Wasim_Video-FocalNets_Spatio-Temporal_Focal_Modulation_for_Video_Action_Recognition_ICCV_2023_paper.pdf (thecvf.com)https://openaccess.thecvf.com/content/ICCV202…

vscode打造舒适的python开发环境

shigen坚持更新文章的博客写手&#xff0c;擅长Java、python、vue、shell等编程语言和各种应用程序、脚本的开发。记录成长&#xff0c;分享认知&#xff0c;留住感动。 个人IP&#xff1a;shigen 背景 突然想写一些python小脚本&#xff0c;提升我的mac使用体验和日常效率提升…

LayUI使用(一)点击树组件的右边空白区域也可响应事件

前提&#xff1a; 如下&#xff0c;希望能够点击右边的空白区域也能够响应&#xff0c;而不仅仅是点击文本才响应 分析流程 一开始问了chatgpt&#xff0c;但它给的方案太麻烦了&#xff0c;而且还有错误&#xff0c;因此自己上手F12进入调试模式&#xff0c;点击查看最终渲…