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.rhkb.cn/news/334965.html

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

相关文章

MM模块六(收货)

接到供应商收到的货以后&#xff0c;进行一个收货的动作 收货&#xff1a;MIGO 1.消耗物料的采购订单 数量是供应商的数量 消耗物料的采购订单&#xff0c;收进来的货物直接进入消耗&#xff0c;不会增加库存&#xff0c;所以这里没有库存地点进行选择 点击过账 收货后在采购…

Epic Pen Pro v3 解锁版安装教程 (屏幕实时标记注释工具)

前言 Epic Pen是一款功能强大的屏幕标记工具&#xff0c;允许您在屏幕上绘图或书写&#xff0c;而无需在后台与软件交互。这意味着您几乎可以注释任何东西&#xff01;使用我们流行的屏幕标记和Windows数字白板工具Epic Pen编写、绘制和突出显示&#xff0c;包括演示文稿软件&…

【Linux】线程安全及锁的使用

文章目录 前言一、锁1.定义一个锁变量2.pthread_mutex_init3.pthread_mutex_destroy4.pthread_mutex_lock/pthread_mutex_unlock5.静态变量锁和全局变量锁的初始化 二、问题描述及锁的运用三、RAII风格的锁 前言 临界资源: 在多个线程或进程间共享的资源. 临界区: 代码中访问临…

目标检测——家庭日常用品数据集

引言 亲爱的读者们&#xff0c;您是否在寻找某个特定的数据集&#xff0c;用于研究或项目实践&#xff1f;欢迎您在评论区留言&#xff0c;或者通过公众号私信告诉我&#xff0c;您想要的数据集的类型主题。小编会竭尽全力为您寻找&#xff0c;并在找到后第一时间与您分享。 …

maven聚合工程整合springboot+mybatisplus遇到的问题

前言&#xff08;可以直接跳过看下面解决方法&#xff09; 项目结构 两个module&#xff1a; yema-terminal-boot 是springboot项目&#xff0c;子包有&#xff1a;controller、service、dao 等等。属于经典三层架构。那么&#xff0c;该module可以理解为是一个单体项目&…

uniapp - 填充页面

在上一篇文章中&#xff0c;创建了一个空白的文章模块页面。在这一篇文章&#xff0c;让我们来向页面中填充内容。 目录 页面效果涉及uniapp组件1.view2.swiper3.scroll-view4.属性解读1) class"style1 style2 .."2) circular单属性无赋值3) :autoplay"autoplay…

SpringSecurity6从入门到实战之SpringSecurity快速入门

SpringSecurity6从入门到实战之SpringSecurity快速入门 环境准备 依赖版本号springsecurity6.0.8springboot3.0.12JDK17 这里尽量与我依赖一致,免得在学习过程中出现位置的bug等 创建工程 这里直接选择springboot初始化快速搭建工程,导入对应的jdk17进行创建 直接勾选一个web…

使用Python发送电子邮件

大家好&#xff0c;当我们需要迅速、方便地与他人沟通时&#xff0c;电子邮件是无疑是一种不可或缺的通信工具。无论是在个人生活中还是工作场合&#xff0c;电子邮件都是我们日常生活中的重要组成部分。它不仅能够传递文字信息&#xff0c;还可以发送附件、链接和嵌入式多媒体…

如何将音频中的人声分离出来?

想要把一段视频中的人声跟背景音乐分离开来&#xff0c;找个好一点的音频处理软件就能把声音分离了&#xff0c;常见的有以下方法&#xff0c;一起来看看吧。 pr 打开软件&#xff0c;然后将电脑上的音频文件&#xff0c;上传到软件中&#xff0c;然后按住[ctrla]选择所有音频…

Android 布局中@NULL的使用和代码实现方式详解

文章目录 1、使用场景2、示例代码实现2.1、移除背景2.2 、移除文本2.3、移除布局宽度或高度2.4、移除提示文本2.5、移除图像资源 3、综合示例3.1、布局文件 activity_main.xml3.2、主活动文件 MainActivity.java3.4、资源文件3.5、运行结果 4、优点5、缺点6、综合分析6.1、适用…

若依启动run-modules-system.bat报错问题解决方案

在启动run-modules-system.bat时遇到了一些问题,在网上搜索无果后,排查解决完毕 1.启动nacos时,报错如下 Error creating bean with name grpcClusterServer: Invocation of init method failed; nested exception is java.io.IOException: Failed to bind to address 0.0.0.0…

AlexNet神经网络训练

导包 import tensorflow as tffrom tensorflow.keras import datasets, layers, models 加载Fashion-MNIST数据集 (train_images, train_labels), (test_images, test_labels) datasets.fashion_mnist.load_data() 归一化像素值到[0, 1]区间 train_images, test_images t…

齿轮常见故障学习笔记

大家好&#xff0c;这期咱们聊一聊齿轮常见的失效形式&#xff0c;查阅了相关的资料&#xff0c;做个笔记分享给大家&#xff0c;共同学习。 介绍 齿轮故障可能以多种方式发生。如果在设计阶段本身就尽量防止这些故障的产生&#xff0c;则可以产生改更为优化的齿轮设计。齿轮…

Burnout Drift Multiplayer(多人赛车游戏模板)

Burnout Drift Multiplayer是一个完整的项目,已在PC、Android、iOS和WebGL上发布的Burnout Drift系列中使用。 [包括最新版本的Realistic Car Controller Pro] PC、WebGL和Android演示 包括Burnout Drift系列的所有功能。您只需几分钟即可轻松添加自己的车辆、场景和配乐。 警…

【Python】【Scrapy 爬虫】理解HTML和XPath

为了从网页中抽取信息&#xff0c;必须对其结构有更多了解。我们快速浏览HTML、HTML的树状表示&#xff0c;以及在网页上选取信息的一种方式XPath。 HTML、DOM树表示以及XPath 互联网是如何工作的&#xff1f; 当两台电脑需要通信的时候&#xff0c;你必须要连接他们&#xff…

NFT Insider #131:Mocaverse NFT市值破3.5万ETH,The Sandbox 参加NFCsummit

引言&#xff1a;NFT Insider由NFT收藏组织WHALE Members&#xff08;https://twitter.com/WHALEMembers&#xff09;、BeepCrypto &#xff08;https://twitter.com/beep_crypto&#xff09;联合出品&#xff0c;浓缩每周NFT新闻&#xff0c;为大家带来关于NFT最全面、最新鲜、…

【LLM第7篇】transformer跟bert、gpt、大模型的联系

上一篇讲了transformer的原理&#xff0c;接下来&#xff0c;看看它的衍生物们。 Transformer基本架构 Transformer模型主要由两部分组成&#xff1a;编码器&#xff08;Encoder&#xff09;和解码器&#xff08;Decoder&#xff09;。编码器负责处理输入序列&#xff0c;将其…

linux解压.zip文件命令详解

在Linux中解压.zip文件&#xff0c;你可以使用unzip命令。如果你的系统中没有安装unzip&#xff0c;你可以使用包管理器来安装它。 Debian的系统&#xff08;Ubuntu&#xff09;&#xff0c;安装命令&#xff1a; sudo apt-get install unzip基于Red Hat的系统&#xff08;如…

STM32-11-电容触摸按键

STM32-01-认识单片机 STM32-02-基础知识 STM32-03-HAL库 STM32-04-时钟树 STM32-05-SYSTEM文件夹 STM32-06-GPIO STM32-07-外部中断 STM32-08-串口 STM32-09-IWDG和WWDG STM32-10-定时器 STM32电容触摸按键 电容触摸按键原理&#xff1a; 无手指触摸&#xff1a;上电时&…

Pytorch环境配置2.0.1+ Cuda11.7

查找cuda、cudnn、Pytorch(GPU)及cuda和NVIDIA显卡驱动对应关系 查询可支持的最高cuda版本 nvidia-smi查看支持的cuda的版本 CUDA版本对应表 我的显卡驱动是Driver Version&#xff1a;535.40.&#xff0c;那么左边对应的CUDA都可以兼容 右上角为CUDA 版本&#xff0c;可以看…