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的句柄的mapTMap<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(); }*///获取ASCUAbilitySystemComponent* 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;//在是无限时间效果和需要在结束时清除掉时,将效果句柄添加到mapif(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);}}
}

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

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

相关文章

Vue3实战笔记(39)—封装页脚组件,附源码

文章目录 前言一、封装页脚组件二、使用组件总结 前言 在Web开发中&#xff0c;页脚组件是一个重要的部分&#xff0c;它为用户提供关于网站的信息、导航链接以及版权声明等。而封装页脚组件则是一种高效的方法&#xff0c;可以提高代码的可重用性和可维护性。 一、封装页脚组…

重生之我要精通JAVA--第五周笔记

文章目录 APIJDK7时间Date时间类CalendarSimpleDateFormat 类SimpleDateFormat 类作用 JDK8时间Zoneld时区 包装类Integer成员方法 Arrays Lambda表达式标准格式注意点好处省略写法 集合进阶Collection迭代器遍历Collection集合获取迭代器Iterator中的常用方法细节注意点 增强f…

机器学习势系列教程(3):cp2k的安装

大家好&#xff0c;我是小马老师。 本文继续介绍机器学习势相关内容&#xff1a;cp2k的安装。 和abacus一样&#xff0c;cp2k也是一款开源的第一性原理模拟软件&#xff0c;模拟的数据也可作为机器学习势的训练数据集。 cp2k安装方法也很多&#xff0c;常见的有docker安装、…

2024年中国电机工程学会杯数学建模思路 - 案例:最短时间生产计划安排

# 前言 2024电工杯(中国电机工程学会杯)数学建模思路解析 最新思路更新(看最新发布的文章即可): https://blog.csdn.net/dc_sinor/article/details/138726153 最短时间生产计划模型 该模型出现在好几个竞赛赛题上&#xff0c;预测2022今年国赛也会与该模型相关。 1 模型描…

安当SLA操作系统双因素认证——成功解决Windows远程桌面登录的安全问题

Windows远程桌面登录的安全风险主要包括以下几个方面&#xff1a; 弱密码和暴力破解&#xff1a;如果远程桌面用户使用了弱密码&#xff0c;或者密码被泄露&#xff0c;攻击者可能会使用暴力破解技术来尝试猜测密码&#xff0c;从而获取远程桌面的访问权限。中间人攻击&#x…

【编译原理复习笔记】语法分析-补充(二义性与LR错误处理)

二义性文法的 LR 分析 每个二义性文法都不是 LR 的 但是某些二义性文法更加简短&#xff0c;描述更方便 如 I7 和 I8 具有移进归约冲突 使用优先级和结合性解决冲突 对于 I7&#xff0c;由于乘号优先级高于加号&#xff0c;所以当下一个输入符号为乘号时&#xff0c;我们优…

pdfbox pdf转换图片时中文丢失,变成方框,提示No glyph for xxx in font STSong-Light

使用pdfbox转换图片时&#xff0c;转换出来的图片中文丢失&#xff0c;变成方框。原因是由于服务器字体缺失&#xff0c;pdfbox在转换时找不到合适的字体。 有几种方案&#xff1a; 服务器安装字体&#xff0c;具体资源百度使用备用字体。 将pdfbox中的FontMapperImpl类&…

Android 逆向学习【2】——APK基本结构

APK安装在安卓机器上的&#xff0c;相当于就是windows的exe文件 APK实际上是个压缩包 只要是压缩的东西 .jar也是压缩包 里面是.class(java编译后的一些东西) APK是Android Package的缩写,即Android安装包。而apk文件其实就是一个压缩包&#xff0c;我们可以将apk文件的后…

RabbitMQ安装及配套Laravel使用

MQ MQ 全称 Message Queue(消息队列),是在消息的传输过程中保存消息的容器。多用于系统之间的异步通信。 为什么需要mq: 解耦:MQ能够使各个系统或组件之间解耦,降低它们之间的耦合度,提高系统的灵活性和可维护性异步处理:通过MQ可以实现异步处理,提高系统响应速度和吞…

后量子密码解决方案

什么是后量子密码学 (PQC)&#xff0c;为什么准备工作如此重要? 量子计算正在迅速发展;用不了多久&#xff0c;量子网络攻击就会成为可能。量子网络攻击将能够在几分钟内瘫痪大型网络。我们今天赖以保护我们的连接和交易的一切都将受到量子计算机的威胁&#xff0c;危及所有密…

PostgreSQL学习:关于PostgreSQL以及认证

1、关于PostgreSQL PostgreSQL&#xff08;简称PG&#xff09;是强大的企业级开源关系数据库&#xff0c;世界排名第四&#xff0c;前三位Oracle 、SQLServer、MySQL都是商业数据库或受商业主体的控制&#xff0c;PG是学术社区开源数据库&#xff0c;开源协议自由度非常高&…

免费开源人脸识别系统,支持RESTful API

简介 CompreFace 是一个免费开源的人脸识别项目&#xff0c;您不需要具备机器学习技能就能安装设置和使用 CompreFace&#xff0c;官方提供了基于 docker 的部署方法&#xff0c;可以方便地部署在本地或者云端服务器上。 CompreFace 提供了 RESTful API&#xff0c;用于人脸识别…

Springboot 多环境切换 方法

准备工作 假设系统中有以下几个yml文件&#xff1a; application.ymlapplication-dev.ymlapplication-prode.ymlapplication-test.yml 方法一&#xff1a;在Active Profiles:输入dev 启动效果&#xff1a; 方法二&#xff1a;在Environment variables: 输入spring.profile…

Dijkstra算法在《庆余年》中的应用:范闲的皇宫之旅

❤️❤️❤️ 欢迎来到我的博客。希望您能在这里找到既有价值又有趣的内容&#xff0c;和我一起探索、学习和成长。欢迎评论区畅所欲言、享受知识的乐趣&#xff01; 推荐&#xff1a;数据分析螺丝钉的首页 格物致知 终身学习 期待您的关注 导航&#xff1a; LeetCode解锁100…

GPT‑4o普通账户也可以免费用

网址 https://chatgpt.com/ 试了一下&#xff0c;免费的确实显示GPT‑4o的模型&#xff0c;问了一下可以联网&#xff0c;不知道能不能通过插件出图 有兴趣的可以试试

Acrobat Pro DC 2024 Mac软件安装包下载PDF2024 Mac安装教程

安装 步骤 1&#xff0c;双击打开下载好的安装包。 2&#xff0c;选择acrobat dc installer.pkg双击启动安装程序。 3&#xff0c;点击继续。 4&#xff0c;点击继续。 5&#xff0c;点击继续。 6&#xff0c;点击安装。 7&#xff0c;输入电脑密码。 8&#xff0c;软件安装中…

“手撕”String类+练习题

一、什么是String类 简单讲&#xff1a;是一个类&#xff01;创建字符串和字符串方法的类。 用 圈起来的叫字符&#xff0c;比如&#xff1a;a,b....里面只能有一个char类型的字符。 用" "圈起来的叫字符串&#xff0c;比如&#xff1a;"abc"..里面可以连…

如何搭建Sphinx文档

环境准备 Linux CentOS 7 方案 搭建一个文档网站&#xff0c;本文档使用的是tomcatsphinx。 Tomcat可以快速搭建出http服务&#xff0c;也可以使用apache httpd。 Sphinx作为文档网页自动生成工具&#xff0c;可以从reStructured文档转换为html文件。 Tomcat安装 创建/…

华为设备WLAN配置之AP上线

WLAN基础配置之AP上线 配置WLAN无线网络的第一阶段&#xff0c;AP上线技术&#xff1a; 实验目标&#xff1a;使得AP能够获得来自AC的DHCP地址服务的地址&#xff0c;且是该网段地址池中的IP。 实验步骤&#xff1a; 1.把AC当作三层交换机配置虚拟网关 sys Enter system view,…

【XuperChain】一、搭建第一条区块链节点

一、准备环境&#xff1a; 下载git和golang即可 apt install git apt install golang二、拉取代码&#xff0c;编译XuperChain 通过此命令拉取XuperChain源码到本地 git clone https://github.com/xuperchain/xuperchain.git 拉取成功后&#xff0c;会代码保存到了xuperChain…