UE4 简单AI

UE4中Pawn是马甲,Controller是驱动马甲的大脑。 Controller和Pawn相对独立,不一定谁必须有谁。一个Controller至多能控制一个Pawn,一个Pawn至多能被一个Controller控制。

在这里插入图片描述

问我为什么不粘代码?不好意思,截图太方便了 ^ _ ^

1.蓝图启动行为树

1)建立行为树与黑板(Behavior Tree、BlackboardData)
此两项放在同一级目录里!否则BTTask里的对BlackBoardData的Data的读写失效等问题。
在这里插入图片描述
在行为树中选中要使用的黑板
在这里插入图片描述
2)创建AIcontroller,在AIcontroller下执行useblackboard和runbehaviourtree节点
在这里插入图片描述
3)创建BP类,一般继承自Pawn或Character
在pawn选项中更改两个选项
Auto Possess AI表示是否AI自行启动,调成该选项后,动态生成与摆放在关卡中的AI都会启动行为树,默认选项仅摆放在关卡中的AI会启动行为树
AI Controler Class中选定当前AI要用的AIController类
在豆腐干地方地方官梵蒂冈梵蒂冈地方官里插入图片描的的述

2.使用C++直接属性引用得到蓝图中的行为树,并自行控制启动与停止

1)建立C++类的AIController类
建立三个指针变量,行为树组件、黑板组件、行为树
在这里插入图片描述
.cpp中需引入组件相关头文件
在这里插入图片描述

2)构造函数中创建组件
在这里插入图片描述

3)自行构造两个函数,用与启动或停止行为树
在这里插入图片描述

4)重写虚函数Posses与UnPosses,设置黑板数据并启动行为树
在这里插入图片描述
调用StartBTree与StopBTree方法,为启动与停止行为树,可在适当时候调用,可以适时启动与停止行为树。(可能并不需要?或不该这么做?)

5)创建蓝图子类继承自C++的AIController,选取要使用的行为树
在这里插入图片描述

行为树优点

1.结构清晰
2.便于调试
3.适用于成群的AI或大量逻辑行为相似的AI

行为树中的黑板

1.行为树中的核心模块
2.用于支撑行为树中的数据存储和读取
3.相当于我们的草稿纸,我们可以把需要参与逻辑的数据罗列在上面
4.使用方便,数据扩展性强
5.有较好的维护性

行为树中的5个节点

1.Composite,这种节点定义一个分支的根以及该分支如何被执行的基本规则
2.Task,这种节点是行为树的叶子,实际“执行”操作,不含输出连接
3.Decorator,即为条件语句。这种节点附着于其他节点,决定着树中的一个分支,甚至单个节点是否能被执行
4.Services,这种节点附着在 Composite 节点上,只要其分支节点被执行,它们便将按所定义的频率执行。它们常用于检查和更新黑板。
5.Root,根节点,无法被附着,可以用来设置黑板数据

行为树中的Composite

在这里插入图片描述
1.Selector,从左至右执行,只要有一个子项条件成立,则停止向下执行。任意子项成立,则selector成立
2.Sequence,从左至右执行,只要有一个子项不成立,则停止执行剩余项。所有子项成立,则sequence成立
3.Simple Parallel,并行树,允许单个任务在任务树旁执行。Finish Mode 中的设置将确定节点是否立即完成、是否终止次要树,或是否延迟次要树的完成

行为树中的Service、Decorator、Task

1.Service服务
附着在Composite节点上
可以按照指定的频率执行
主要意图在于检查和更新黑板内容
它们以行为树系统的形态取代了传统平行节点
我们一般会重写此节点

2.Decorator装饰器
Blackboard,借助一个黑板数据,进行逻辑操作判定
Compare Blackboard Entries,对比黑板内两个数据
Cone Check,锥形检测,可以检测目标是否在锥形范围内
Cooldown,锁定节点或是分支,直到时间结束
Does Path Exist,检查AB两点见路径是否可行
Force Success decorator 将节点结果改为成功
Is At Location,检查AI控制的角色是否在指定的位置
Keep in Cone,持续检查锥形范围内目标
Loop,以一定次数或是无限次数循环节点
TimeLimit,节点逻辑时间定时器

NONE,不终止执行
Self,中止 self,以及在此节点下运行的所有子树
Lower Priority,中止此节点右方的所有节点
Both,终止 self、此节点下运行的所有子树、以及此节点右方的所有节点

以上逻辑操作,试用于装饰器

3.Task任务节点
真正在干活的角色
可以重写,支持扩展
UE提供了很多基本的任务节点
Make Noise,制造噪音,需要Pawn带PawnNoiseEmitter组件,其他Pawn如果带有PawnSensing组件,则可以听到噪音
Move To移动到目标点,通过黑板提供
Play Sound 播放声音
Run Behavior 执行其他行为树
Wait,Wait BB Time,等待事件,无法被终止
Play Anim,促使控制Pawn播放动画

创建

蓝图建立,在行为树顶端建立即可
在这里插入图片描述
1)建立Services
2)建立Decorator
3)建立Task

C++建立
1)建立Services,命名规则一般为BTService_***继承自BTService
需重写两个虚函数OnGameplayTaskActivated、OnGameplayTaskDeactivated并Super再重新编译,起始创建时会报错,不要慌。重写的逻辑一般写在在TickNode,记住Super。
在这里插入图片描述

2)建立Decorator,命名规则一般为BTDecorator_***继承自BTDecorator
需重写三个虚函数
在这里插入图片描述

3)建立Task,命名规则一般为BTTask_***继承自BTTaskNode
需要重写三个虚函数OnGameplayTaskActivated、ExecuteTask、InitializeFromAsset,Super后再重新编译,主要的任务行为写在ExecuteTask里,可以用OwnerComp.GetAIOwner()->GetPawn()得到该AIPawn。(需要引入头文件#include “AIController.h”)

AI感知组件PawnSensingComponent 一个神奇的组件

1.听力阙值(能够听到声音的大小)
2.LOS听力阙值(未被遮挡的情况下?)
3.视觉半径
4.传感区间
5.听觉最大年龄?(我们能听到的声音的最大年龄。应该大于感觉间隔,否则你可能会错过听到一些声音)
6.能够让传感更新?
7.是否仅感觉玩家(若要AI之间相互互动,能看到或听到其他AI,需改为false)
8.能够看到pawn
9.能够听到噪音
10.周边视觉角度(可理解为AI发出的锥形检测的角度)
在这里插入图片描述

增加了3种辅助线(视觉范围,无障碍听觉范围,障碍听觉范围)
在这里插入图片描述

以下从别的大佬那粘的

1.视觉

关于视觉还要说的一点就是PawnSensingComponent的CouldSeePawn和HasLineOfSightTo函数,这两个函数看名字可能觉得差不多,但是功能不太一样。总体来说:
1)CouldSeePawn仅仅简单地判断你给出的Pawn是否在锥形内。(这个考虑了锥形的覆盖,但是没有考虑遮蔽)
2)HasLineOfSightTo仅仅简单地判断你给出的Pawn是否内被这个PawnSensingComponent看见(这个又没有考虑锥形的覆盖,只考虑了遮挡)
可见真正要达到“看得见”这个目标,还是要同时进行CouldSeePawn和HasLineOfSightTo两个判断。实际上PawnSensingComponent内部判断是否能看见时,也是用的这两个,我们看看部分代码:

bool bHasSeenPawn = false;
bool bHasFailedLineOfSightCheck = false;
    if (bSeePawns && ShouldCheckVisibilityOf(&Pawn))
    {
    
    
        if (CouldSeePawn(&Pawn, true))
        {
    
    
            if (HasLineOfSightTo(&Pawn))
            {
    
    
                BroadcastOnSeePawn(Pawn);
                bHasSeenPawn = true;
            }
            else
            {
    
    
                bHasFailedLineOfSightCheck = true;
            }
        }
    }

	APawn* pawn = nullptr;
	AActor* actor = nullptr;
	bool a = SensingCom->CouldSeePawn(pawn);
	bool b = SensingCom->HasLineOfSightTo(actor);

添加代理回调 按照源码中DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam( FSeePawnDelegate, APawn*, Pawn );添加回调,类似添加碰撞的触发函数
切记//动态绑定函数切记需要添加函数标记宏

UFUNCTION()
void OnSeePlayer(APawn* Pawn);
//BeginPlay中
	SensingCom->OnSeePawn.AddDynamic(this, &ARabbitCharacter::OnSeePawn);

2.听觉

添加代理回调

	DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams( FHearNoiseDelegate, APawn*, Instigator, const FVector&, Location, float, Volume);
切记//动态绑定函数切记需要添加函数标记宏
UFUNCTION()
void OnHearNoise(APawn* PawnInstigator, const FVector& Location, float Volume);
//BeginPlay中
	SensingCom->OnHearNoise.AddDynamic(this, &ARabbitCharacter::OnHearNoise);

在主角头文件中UPawnNoiseEmitterComponent组件
UPROPERTY()
class UPawnNoiseEmitterComponent* NoiseEmitterCom;
在主角构造函数中初始化组件
先引入头文件,#include “Components/PawnNoiseEmitterComponent.h”
构造函数中NoiseEmitterCom = CreateDefaultSubobject(TEXT(“NoiseEmitter”));
在主角色中,发声的回调函数中(可绑定到动画通知事件中)调用函数MakeNoise即可,此函数为AActor类中函数,填入对应参数即可

此函数为发出声音,意图让AI听到

void AActor::MakeNoise(float Loudness, APawn* NoiseInstigator, FVector NoiseLocation, float MaxRange, FName Tag);

猜你喜欢

转载自blog.csdn.net/qq_37195273/article/details/106334343