UE4 AI

news/2025/3/19 16:00:29/文章来源:https://www.cnblogs.com/XTG111/p/18225359

UE4中的AI

UE4中AI一般通过行为树来实现

行为树控制了AI的动作,而该执行哪些动作则是由AIController(本质上是一个类)进行判断,然后传入BlackBoard的Key中,之后在行为树里利用Selector或者Sequence进行执行对应的动作
每个Actor类都可以选择一个AIController类

行为树中的两个节点

Selector: 选择执行,即多个人物只能选择一个执行,任务之间相互独立没有依赖性
Sequence:顺序执行,其下属多个任务从左至右依次执行,如果左边的任务失败,右边的任务不会被执行

任务

就是AI的行为,UE已经内置了MoveTo和Wait之类的任务。也可以自己新建任务,注意任务中的参数都是通过BlackBoard传输的。
即AIC对BlackBoard的值进行传输,Task可以自定义参数接受BlackBoard中的值

Decorator

可以用于判断,通过重载PerformConditionCheckAI,可以设置Bool来控制之后的Task是否执行

蓝色的就是Decorator,,如果其为false将不会执行后续动作,会导致Sequence左边的所有任务失效

AI感知

需要在AIController中添加AIPerception组件

AI的眼睛,耳朵等。以AISight为例

可以对其属性进行分配设置。

获取感知结果

可以通过AIPerception组件的GetActorPerception获取已经配置的所有感知组件感知的结果

然后可以编写对应组件感知到之后的BlackBord中Key的变化,从而在行为树中AI可以选择对应的行为执行

C++实现

C++实现主要是实现AIController和BTTask等,对于行为树和BlackBoard直接在UE中设置就好,所以需要在AIController选择对应的行为树。

BTTask和BTDecorator

一般来说想要写的Decorator可以继承UBTDecorator,然后重写CalculateRawConditionValue函数
而对于Task则可以继承UBTTaskNode或者UBTTask_BlueprintBase,重写ExecuteTask函数即可
这两个函数都是返回的EBTNodeResult枚举值,用来表示当前这些结果,而函数中主要的参数就是UBehaviorTreeComponent& OwnerComp,通过干参数可以获得AIController,然后通过AIController就可以得到Character了

AXAIController* AICon = Cast<AXAIController>(OwnerComp.GetAIOwner());
AXAI_Character* ControlledPawn = Cast<AXAI_Character>(AICon->GetPawn());

延迟返回

对于一些情况,可能希望BTTask要延迟一段时间,再进行返回EBTNodeResult::Type,有一种方法就是首先在原本的ExecuteTask中返回EBTNodeResult::InProgress,然后在延时返回的函数中使用FinishLatentTask函数,返回EBTNodeResult::Succeeded。
有一种情况就是AI攻击时,一般是需要Montage动画播放完成才能进行之后的行为。
具体的方法可以是利用委托,当Montage结束后进行广播,当然此时广播的是无参数的。在BTTask中,可以将该委托绑定一个函数,该函数执行另一个委托绑定FinishLatentTask函数

//BTTask.h
//利用UE给的一个单播委托绑定,并且可以利用单播委托添加负载
FSimpleDelegate FinishDelegate;//BTTask.cpp
FinishDelegate.BindUObject(this, &UXBTTask_DefaultAttack::FinishLast, &OwnerComp);
ControlledPawn->CallOnAttackEndCall.Clear();
ControlledPawn->CallOnAttackEndCall.AddDynamic(this, &UXBTTask_DefaultAttack::Finish);
ControlledPawn->Attack();//当蒙太奇播放完进行调用
void UXBTTask_DefaultAttack::Finish()
{UE_LOG(LogTemp, Warning, TEXT("FinishAttack"));//执行DelegateFinishDelegate.ExecuteIfBound();
}//调用FinishLatentTask
void UXBTTask_DefaultAttack::FinishLast(UBehaviorTreeComponent* OwnerComp)
{UE_LOG(LogTemp, Warning, TEXT("FinishNode"));FinishLatentTask(*OwnerComp, EBTNodeResult::Succeeded);
}

蒙太奇播放完成通知

UE已经定义了一个Delegate用来处理蒙太奇播放完成的情况OnMontageEnded,只需要绑定函数即可

//XAICharacter.cpp
void AXAI_Character::Attack()
{GetMesh()->GetAnimInstance()->OnMontageEnded.Clear();PlayAnimMontage(AttackMontage);GetMesh()->GetAnimInstance()->OnMontageEnded.AddDynamic(this, &AXAI_Character::EndAttackMontage);
}void AXAI_Character::EndAttackMontage(UAnimMontage* Montage, bool bInterrupted)
{CallOnAttackEndCall.Broadcast();
}

EQS

就是根据设置的标准,返回AI周围的游戏环境中的一系列点或者一个点给AI,从而不再局限于仅仅是对Pawn的追踪功能。而可以实现在Pawn周围围绕。
在C++下可以新建继承于UEnvQueryContext_BlueprintBase的类,重写ProvideContext函数,用来获取EQS范围的中心

//获得AI对象Actor
UObject* QObject = QueryInstance.Owner.Get();
AXAI_Character* ControlledPawn = Cast<AXAI_Character>(QObject);
//获得EQS环境产生的圆心为被攻击的角色
AActor* AttackTarget = AIC->GetAttackTargetActor();
UEnvQueryItemType_Actor::SetContextHelper(ContextData, AttackTarget);

在UE中通过设置点的个数和圆半径,即可得到AI可以移动的点

之后就可以在行为树中,Run EQS,选择EQS资源和对应需要修改的黑板键值,即可完成初步的实现

可以发现的是,默认的EQS下目标点的权重都是1,那么AI就会在这些点随机移动,所以应该进行设置,当在一个点时,其两边的点权值变高。
可以在EQS树中,添加DistanceTest,通过控制Test的范围来修改当前点可以到达的点,从而自动修改了权值
image
这种方法可以有效的避免,AI从圆的内部穿过

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

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

相关文章

一文了解JVM(中)

HotSpot 虚拟机对象探秘 对象的创建Header 解释使用 new 关键字 调用了构造函数使用 Class 的 newInstance 方法 调用了构造函数使用 Constructor 类的newInstance 方法 调用了构造函数使用 clone 方法 没有调用构造函数使用反序列化 没有调用构造函数说到对象的创建,首先让我…

FFT 学习笔记

多项式 复数 单位根 DFT IDFT FFTFFT 学习笔记 1.多项式与卷积 1.1 多项式 对于多项式 \(F(x)=a_0+a_1x+a_2x^2+a_3x^3+\dots+a_nx^n\),我们称 \(a_0,a_1,\dots,a_n\) 为它的系数,这种表示法叫做系数表示法。 定义 \(F(x)\) 的 \(n\) 次项系数为 \(f_n\)。 我们有: \[F(x)=…

题目集4-6的总结性Blog

一.前言: 在这几周,我们又进行了3次pta的题目训练。 首先是答题程序的最后一次迭代,答题程序-4,接着就是新的迭代,家居电路模拟程序。经过一段时间的学习,我对面向对象设计的理解进一步加深,这三次题集写起来也没有之前那么困难了,虽然还有不足,我仍在一次次答题中学…

Kubernetes – 架构

Kubernetes 集群主要由称为节点的工作机器和控制平面组成。集群中至少有一个工作节点。Kubectl CLI 与控制平面通信,控制平面管理工作节点。 Kubernetes – 集群架构 如下图所示,Kubernetes 采用客户端-服务器架构,有主节点和工作节点,主节点安装在单个 Linux 系统上,而节…

九、FreeRTOS学习笔记-列表和列表项

列表和列表项的简介 列表是 FreeRTOS 中的一个数据结构,概念上和链表有点类似,列表被用来跟踪 FreeRTOS中的任务。 列表项就是存放在列表中的项目列表相当于链表,列表项相当于节点,FreeRTOS 中的列表是一个双向环形链表 列表的特点:列表项间的地址非连续的,是人为的连接到…

我真的从测试转成了开发......

写在前面 因为走的圈太大了,早上上班差点迟到,幸好有我每日5公里的加持,侥幸踩点进办公室,哈哈,真的好险! 我开发的功能不能用了 上午开始着手某功能的开发,还在写后台逻辑。 结果到了下午,由于前端同学的代码冲突,打包发布后,导致我写的功能直接不能用了,瞬间emo了…

手把手教你用VM搭建Linux系统

手把手教你用VM搭建Linux系统一、安装vm 查看是否安装成功,打开网络适配器(win+R+ncpa.cpl) 确保有 VMnet1 和 VMnet8二、创建虚拟机step01step02step03 密码123456(我怕我忘了),全名是对你的虚拟机的别称没什么太大作用,用户名代表你说什么用户会涉及到权限step04,位置…

kettle从入门到精通 第六十五课 ETL之kettle 执行动态SQL语句,轻松实现全量增量数据同步

本次课程的逻辑是同步t1表数据到t2表,t1和t2表的表机构相同,都有id,name,createtime三个字段。 CREATE TABLE `t1` (`id` bigint NOT NULL AUTO_INCREMENT,`name` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,`createtime` datetime DEFAUL…

HMI-Board之LVGL应用

LVGL应用示例移植 使用默认模板工程新建一个RT-Thread项目,BSP版本为1.1.1打开RT-Thread Settings,点击右侧箭头按钮进入详细页,在硬件栏开启以下几个配置选项(LCD、触摸屏、demo)此时,打开board文件夹,发现下面会有一个lvgl的目录,package目录下会有LVGL和lv-music两个…

升鲜宝牛奶溯源管理系统_2024年全网首发,针对牛奶行业特定的溯源解决方案_一码一物_升鲜宝_余东升_升鲜宝供应链管理系统团队再出新作。

升鲜宝牛奶溯源管理系统_2024年全网首发,针对牛奶行业特定的溯源解决方案_一码一物_升鲜宝_余东升_升鲜宝供应链管理系统团队再出新作。整套软件解决方案分三个端:1.PC后台溯源管理系统2.uniapp溯源小程序员工操作端3.vue3,h5溯源网页展示效果图主要功能:权限管理(组织机构、…

如何设计兜底方案(高可用)

场景: 很多时候,在同步数据时,都会有一个重新推送的按钮,不管是重新推送还是重新拉去。这些动作都是失败后,再次操作,直到成功。这种设计的原因是,程序的运行,不知道什么原因会失败。网络、数据库、服务器,B服务BUG都会导致这段代码执行失败,从而无法保证该功能准确执…