首页 > 其他分享 >UE4 AI

UE4 AI

时间:2024-06-04 23:13:53浏览次数:17  
标签:函数 AIController AI 可以 UE UE4 EQS

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"));
    //执行Delegate
	FinishDelegate.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从圆的内部穿过

标签:函数,AIController,AI,可以,UE,UE4,EQS
From: https://www.cnblogs.com/XTG111/p/18225359

相关文章

  • AI 绘画爆火背后:扩散模型原理及实现
    节前,我们星球组织了一场算法岗技术&面试讨论会,邀请了一些互联网大厂朋友、参加社招和校招面试的同学。针对算法岗技术趋势、大模型落地项目经验分享、新手如何入门算法岗、该如何准备、面试常考点分享等热门话题进行了深入的讨论。合集:持续火爆!!!《AIGC面试宝典》已圈粉无......
  • 王炸AI助手出现,内容生态或将颠覆!
    距离GPT的面世已经经过了很长时间,无论是百度,阿里都在发力,推出自己的大模型。但是,腾讯却一直没有太大的动静。腾讯的混元大模型内测了很长时间,在今天终于与大家见面,名字叫元宝。可能大家会比较好奇,会什么这大模型名字会叫元宝?难道代表了money吗?然而,事实是:深度体验之后,我......
  • Analysis the domain name of Baidu
    /**********************************************************************************************************filename:hw.c*author:[email protected]*data:2024/06/04*function:设计程序实现解析www.baidu.com的域名,把获取到的百度......
  • 掌握三大秘籍,普通人也能轻松驾驭AI大模型:告别技术焦虑,快速上手攻略
    机器学习项目成功的关键,在于对问题的深刻理解,而非算法的选择。——彼得·诺维格(PeterNorvig)谷歌研究总监,人工智能专家这是互联网悦读笔记五一后正式复更的第一天。也是我开始系统化对外输出AI思考的第一篇文章。熟悉这个号的朋友大概能猜到,24年初开始,我就把主要精力投......
  • 初始化容器——initContainers
    转自:https://blog.csdn.net/qq_47261578/article/details/119646847 [root@k8s-master~]#viminit-pod.yaml[root@k8s-master~]#catinit-pod.yamlapiVersion:v1kind:Podmetadata: name:myapp-pod labels:   app:myapp-podspec: containers:   -name:m......
  • T461430 「Daily OI Round 4」Mine
    T461430「DailyOIRound4」MineT461430「DailyOIRound4」Mine解题思路首先,有个简单的想法就是我们考虑选择的那个采矿点是谁,但是我们发现,如果直接算,会重复,比如采矿点\(A\)和采矿点\(B\)所能采集的线段集合如果有交,显然会方案数会重复。这里学到一个计数的技巧:考......
  • containerd 源码分析:创建 container(三)
    文接containerd源码分析:创建container(二)1.2.2.2启动task上节介绍了创建task,task创建之后将返回response给ctr。接着,ctr调用task.Start启动容器。//containerd/client/task.gofunc(t*task)Start(ctxcontext.Context)error{ r,err:=t.client.TaskServi......
  • 设计程序实现解析www.baidu.com的域名,把获取到的百度的IP地址全部输出到终端并验证是
    目录题目分析代码结果题目设计程序实现解析www.baidu.com的域名,把获取到的百度的IP地址全部输出到终端并验证是否正确。分析1.通过目标域名获取目标IP地址对应的网络字节序(需强转为对应的类型),使用gethostbyname()函数;2.把获取的网络字节序转换为点分十进制的IP地址(需强......
  • C语言杂谈:从Hello world说起 #include| main| printf| return
    #include<stdio.h>intmain(){ printf("Hellowworld"); return0;}        打印出“Helloworld”的这个程序相信每个人都是见过的,这段代码非常的简单,没有调用函数,没有使用指针,没有各种杂七杂八的东西,但我相信,第一次看见这个代码的朋友一定会有很多疑问。 ......
  • 2024AIGC应用层十大趋势
    或许你已经关注到了,过去一年,各种大模型、AIGC应用,已经像电子氧气一样:无、处、不、在。而且这种“无处不在”可能还会超出你的预期和想象。IDC发布的《2024AIGC应用层十大趋势》报告就明确了“被AIGC包围”,确实是事实。除此之外,这份权威报告里,还有几点AI的方向也给我激动坏了——......