学习位置
- B站位置:红豆丨泥 UE AI 教程
- 原作者Youtube位置:https://youtu.be/-t3PbGRazKg?si=RVoaBr4476k88gct
- 素材自备
消失在AI的视线里,AI会去自主巡逻
AI视线里的目标消失逻辑
- 首先在AI控制器中新建一个存储AI感官感受到的所有Actor,然后将AI视线看到的所以Actor添加到这个数组中
- 添加一个事件用来判断感官是否忘记看到过的Actor,然后调用函数去改变AI状态
- 函数中当忘记的那个Actor确实是目标时就将AI行为转变为Passive
- 每隔五秒进行一次检查,注意销毁定时器
- 在AI状态枚举中添加一个寻找的状态
- 每添加一个状态就需要添加一个函数用来设置这个状态
- 添加一个函数用来执行失去玩家目标之后的事件
查找最后消失位置行为树逻辑
- 新建一个查找玩家最后消失的位置行为树
- 重写一下注视任务
- 当前Seeking行为树
- 在近战AI行为树中运行,这又AI会追寻玩家到最后消失点位置
EQS让AI在最后消失点进行侦察
- 新建一个EQS
- 添加一个路径测试用来丢弃距离AI太远的点
- 添加追踪测试,来确定AI是否看到面前关卡中的玩家,看到的点就不用去巡逻
- 运用EQS,进行5次EQS巡逻
- 然后设置一下AI控制器中视线感官忘记最后目标的时间
- 所以现在切换状态要么就是20秒忘记了最后目标位置直接进入Passive状态,要么就是执行了5次巡逻后进入Passive状态,要么就是巡逻中途发生其他状态变化会直接打断这5次巡逻的循环然后退出循环
- 然后将那些感官设置可以在Seeking状态时进行切换
- 例如在Seeking状态时,如果发现敌人也会直接进入攻击状态
- 听到声音,就取决于自己是否是去检查声音源,还是继续巡逻查找目标,这里是调查声音源
- AI受到伤害直接进入攻击状态
- 最终Seeking行为树逻辑
注意问题
- 注意这个EQS得根据自己的环境来,当AI走到可以看见面前没有格挡的可以走绿色点时,AI就会停留在原地了
- 此时会因为没有巡逻点而卡停在原地,等待20秒视觉感官消失最后目标后就会进入Passive状态
- 所以此EQS得到的点需要根据自己的项目地图来,墙壁是否多,有很多阻挡隐藏点,主要还是因为这个EQS是面向正前方的扇形,如果将这个扇形生成检查的范围调整可以会不一样
让AI可以在高地形上进行跳跃
Nav Link Proxy
- 导航链接代理
AI跳跃
- 我们新建一个NavLinkProxy蓝图
- 一般AI是默认像右跳的,然后导航链接拥有简单链接与智能链接
- 智能链接需要开启智能链接为相关才能看得见,智能链接只能通过参数进行调整,智能链接与简单链接是两种独立的链接
- 我们一般只用智能链接,因为简单链接不会提供任何事件供我们使用,我们是需要AI到达他们应该跳跃的目标点时发生事件,并且发生最终情况时调用事件所以这仅能在智能链接上调用
- 所以我们会删掉所以简单链接,避免敌人试图采取一条路径并且不具有我们需要实现的跳跃功能
- 我们只需要智能链接,链接的方向是双向的,即可以从左至右,也可以从右至左
- 将这个智能链接添加到地图上
- 在AI接口中添加一个跳跃的函数
- 在基类AI蓝图进行实现这个函数
- 在导航链接中调用这个跳跃函数
- 运行结果
修复失去目标后立即进入Seeking状态
- 设计思路:当目标消失后,设计一个定时器,当定时器到期后则开始搜索,这样当敌人没有玩家目标后,有几秒的缓冲时间来判断是否要进行搜索,因为可能这几秒内又出现了玩家目标就不需要进入搜索状态,让AI更具有灵活性
- 在
HandleLostSight
中把立即切换攻击状态添加上计时器并绑定函数
- 在AI视觉处理函数中,再次看见目标就清除定时器,不需要进行搜索目标了
- 在
HandleLostSight
中把立即切换攻击状态添加上计时器并绑定函数前先清理定时器,确保没有现有定时器
- 进入到攻击目标时也清理定时器
群集AI
毁灭战士的AI令牌系统
- 任何一个可伤害的Actor有,有限数量的令牌, 在被攻击之前,攻击者必须接收到可伤害Actor的令牌,如果没有就不会被攻击。敌人可以相互通信,就像《毁灭战士》的AI系统一样,更高优先级的敌人窃取令牌,彼此之间或相互给予令牌。
- 效果就是AI之间轮流协调攻击
设置令牌系统
- 玩家拥有有限数量的令牌,AI想要攻击就必须得到令牌,完成攻击后将其令牌返回
- 在伤害系统中新建一个函数用来获取攻击令牌,这个函数有返回值,因为获取令牌时要考虑玩家是否拥有这些数量令牌
- 继续新建返回攻击令牌的函数
- 在伤害系统中添加攻击令牌数量变量与要获取的攻击令牌函数
- 新建一个返回攻击令牌的函数,返回的令牌数量与当前的令牌数量相加就是新的令牌数量
- 然后去玩家、敌人蓝图中实现之前在接口中创建的获取令牌与返回令牌两个函数
- 在玩家的构造函数中设置令牌数量
- 在AI的接口当初用来判断攻击是否结束的函数,添加一个输入目标
- 既然攻击函数添加了输入,那默认攻击的任务节点也需要改变
- 在近战AI的攻击事件中去获取令牌进行攻击,只有获取到相应的令牌,才能进行攻击,攻击结束后返回获取到的令牌
- 当时改变了行为树中攻击的任务,记得将目标修改进去
- 运行结果
重构一下攻击系统
- 因为可以发现问题,AI应该在攻击之前就应该判断自己有没有令牌,而不是等到攻击的时候才开始判断自己是否有令牌,所以应该在整个序列之前就应该开始判断,也就是开始下面的整个攻击序列时
- 直接在AI接口中添加三个函数,一个用来攻击开始时获取令牌的判定,一个用来攻击结束,一个用来追踪在玩家哪里拿走的令牌数量
- 然后去AI基类蓝图中实现它们
StoreAttackTokens函数
- 新建一个Map来存储获取令牌的目标与令牌数
- 如果Map中没有相匹配的目标,那么只需要选择B
- 如果有相匹配的目标,那么原本目标的令牌要加上获取到令牌选择A,新值覆盖旧值
AttackStart函数
- 获取令牌,然后进行存储起来
AttackEnd函数
- 攻击结束返回获取到的令牌数量,然后清除Map里面存储的目标的令牌数量
- 顺便调用一下AttackEnd事件分发器,这样就不需要在每个不同的攻击中要去调用这个事件分发器
- 在顺便设置一下Attacking状态
修改一下AI的攻击事件
- 通过上面的攻击系统重构,现在子类的AI,
Attack
函数设置攻击状态只需要继承调用一下父类Attack
函数即可,然后攻击结束只需要调用AttackEnd
函数
- 远程AI也是一样
- 远程AI的获取AttackTarget也不需要了,因为重改的Attack接口函数会传入AttackTarget
重构AI行为树的攻击事件
- 我们把攻击的那个序列的所有任务全部合成一个任务,以便在任何时候该任务失败,我们将返回令牌,这样就不必检查每个任务是否失败
- 新建一个任务用来执行上面的这些任务,注意下面三个图中,
- !!! !!!
Attack
那个函数的Target
线应该是Controller Pawn
连过来,而不是OwnerController
,注意这个错误
- 替换行为树中的攻击任务
- 新建一个任务用来替换远程AI的攻击序列方式
- 替换远程AI行为树
- 我们将攻击与EQS走避分开,这样远程AI没有令牌的时候就会进行EQS的走避
- 为了方便测试将所有AI只攻击玩家一人
- 在AI基类的蓝图死亡函数中设置当AI死亡后也要返回所有的令牌
- 如果想要优化一点AI之间的碰撞问题可以将控制器的父类改为群集AI控制器
群集AI控制器的问题
- !!!!注意:使用了群集AI控制器会影响AI的跳跃机制,换回普通控制器,跳跃就不会有问题