UE4蓝图实现AI智能路径规划与动态移动全流程实战

1. 项目概述:从蓝图到智能移动

在虚幻引擎4(UE4)的开发中,让角色或AI实体在复杂环境中自主、流畅地移动,是许多项目从原型走向成熟的关键一步。无论是制作一款需要NPC巡逻、追击玩家的动作游戏,还是一个模拟无人机或机器人自主作业的仿真应用,智能路径规划与动态移动都是核心需求。这个需求听起来宏大,但UE4强大的蓝图可视化脚本系统,为我们提供了一条从概念到实现的清晰路径,让开发者无需深入底层C++代码,也能构建出相当复杂的AI行为逻辑。

我接手过不少项目,初期大家往往用最简单的“直线移动”或预设路径点来应付,结果就是AI显得很“傻”——撞墙、卡角、在动态障碍物前不知所措。后来我们系统地用蓝图重构了移动逻辑,效果立竿见影。UE4蓝图在这里扮演的角色,就像一个高级的“行为组装车间”。我们不需要从零发明轮子(路径规划算法),而是利用引擎内置的导航系统(NavMesh)作为寻路的基础设施,再通过蓝图去定制“何时寻路”、“如何寻路”以及“寻路后如何移动”这一整套决策与执行链条。

所谓智能路径规划,核心是解决“从A到B怎么走”的问题,并且这个B点可能是动态变化的(比如玩家位置),而路径本身也需要应对环境中突然出现的障碍(动态避障)。动态移动则关注“如何沿着规划好的路径走”,涉及到移动速度、转向平滑度、动画匹配、以及在路径点间如何过渡等细节。将两者结合,就能创造出能绕开桌椅追逐玩家、能在队友身后寻找掩体、或是在仓库中自动规划拣货路线的智能体。

本篇文章,我将以一个实战案例为线索,拆解如何纯粹使用UE4蓝图,一步步构建一个具备环境感知、动态路径重规划和平滑移动能力的AI系统。无论你是刚接触AI编程的蓝图新手,还是想优化现有移动逻辑的开发者,都能从中找到可直接落地的思路和代码块。

2. 核心系统解析:导航网格与AI控制器

在动手连接蓝图节点之前,我们必须先理解UE4为我们准备好的“地基”——导航系统。很多移动问题,根源在于对这个基础系统的理解不透彻。

2.1 导航网格:世界的可通行地图

导航网格(Navigation Mesh,简称NavMesh)是UE4路径规划的物理基础。你可以把它想象成一张铺在所有可行走地表上的隐形“网格地毯”。AI只能在这张地毯覆盖的区域内移动。生成这张地毯的过程,就是让引擎自动分析关卡中所有静态碰撞体的过程,计算出哪些区域是“可行走”的。

在编辑器中生成NavMesh

  1. 在模式面板中,找到“体积”分类,将Nav Mesh Bounds Volume拖入场景。
  2. 调整这个体积框的大小,使其完全包裹住你希望AI能够活动的所有区域。注意,它需要覆盖从地面到预期跳跃高度的空间。
  3. 在顶部菜单栏选择“播放”旁边的下拉箭头,点击“显示”->“导航”,或者直接按P键。你会看到场景中可行走区域被绿色网格覆盖,障碍物区域则为红色。
  4. 如果NavMesh没有生成或显示不全,检查你的地面和静态障碍物是否设置了正确的碰撞预设(通常为BlockAll)。只有被标记为阻挡的物体,NavMesh才会绕开。

注意:NavMesh在编辑器状态下是“静态”计算的,它只考虑那些在构建时不会移动的物体(静态网格体)。对于门、可破坏的箱子、移动的车辆这些动态障碍物,NavMesh本身不会更新,这就需要我们后面提到的“动态避障”技术来补充。

2.2 AI控制器与行为树:大脑与决策树

在UE4的AI框架中,AIController是专门控制Pawn(可以是角色也可以是任何可移动物体)的“大脑”。它和玩家控制器(PlayerController)类似,但专为AI逻辑设计。我们创建的AI角色,其蓝图类中的“AI控制器类”需要指定为我们自定义的AIController蓝图。

行为树(Behavior Tree)是这个大脑的“决策流程图”。它以一种树状结构组织AI的行为逻辑,比直接在角色蓝图里写一堆分支判断要清晰和强大得多。行为树的核心组件包括:

  • 任务(Task):叶子节点,执行具体操作,如“移动到某点”、“等待一段时间”。
  • 装饰器(Decorator):附加在节点上的条件判断,如“是否看到敌人”、“生命值是否低于50%”。
  • 服务(Service):在节点激活时以一定频率执行的后台逻辑,如“更新已知的敌人位置”。
  • 复合节点(Composite):控制子节点执行顺序,如选择器(Selector)(执行第一个成功的子节点)、序列(Sequence)(按顺序执行所有子节点)。

在蓝图中,我们通常会创建一个行为树资源,然后在AIController的BeginPlay事件中,使用Run Behavior Tree节点来启动它。路径规划的核心“移动”任务,就是行为树中的一个标准任务节点。

2.3 蓝图中的关键节点与类

理解几个关键蓝图节点和对象,能让你的开发事半功倍:

  • AI Move To节点:这是实现路径规划和移动的“一站式”节点。你给它一个目标位置或对象,它就会自动为控制的Pawn规划路径并移动过去。它封装了寻路请求、路径跟随等复杂逻辑。
  • Navigation Path对象:当你需要更精细地控制路径,比如先获取路径、进行可视化调试、或对路径点进行自定义处理时,可以使用Find Path to Location Synchronously等节点获取这个对象。它包含了路径上所有关键点(Path Points)的数组。
  • NavMovementComponent:这是Pawn身上负责与导航系统交互的组件。它处理移动指令、应用速度、并处理与物理的交互。通常Character类已内置。
  • EQS(环境查询系统):这是一个更高级的工具,用于让AI基于多重条件(如距离、视线、dot值等)在环境中智能地选择位置,而不仅仅是“移动到某点”。例如,让AI寻找一个既能射击到敌人又有掩体的位置。EQS可以生成一个位置集合并进行评分,最终选出最佳点作为AI Move To的目标。

3. 基础路径规划与移动实现

掌握了核心系统,我们现在开始用蓝图搭建最基础的移动功能。我们从最简单的“移动到固定点”开始,逐步增加复杂性。

3.1 创建AI角色与控制器

首先,我们需要创建AI的实体和它的大脑。

  1. 创建AI角色蓝图:在内容浏览器中右键,选择“蓝图类”,然后以Character为父类创建一个新蓝图,命名为BP_AI_Character。打开后,在“类默认值”的“Pawn”设置中,将“AI控制器类”设置为AIController(或你后续自定义的控制器)。
  2. 创建AI控制器蓝图:同样以AIController为父类创建蓝图,命名为BP_AI_Controller
  3. 创建行为树和黑板:行为树需要一块“黑板(Blackboard)”来存储和共享数据(如目标位置、敌人对象等)。先创建一个Blackboard资源,命名为BB_AI。然后创建一个Behavior Tree资源,命名为BT_AI。打开行为树,在其细节面板中,将“Blackboard Asset”指定为刚创建的BB_AI
  4. 关联控制器与行为树:打开BP_AI_Controller,在事件图表中,于BeginPlay事件后添加Run Behavior Tree节点,将“BT Asset”设置为BT_AI

3.2 使用行为树实现移动任务

现在,我们来配置行为树,让AI能够移动。

  1. 打开BT_AI。从根节点拉出线,添加一个Sequence复合节点。
  2. Sequence下,添加一个Move To任务节点。
  3. 选中Move To节点,在细节面板中,点击“Blackboard Key”旁的“+”号,在黑板BB_AI中创建一个新键,类型为Vector,命名为TargetLocation。然后将Move To节点的“Blackboard Key”设置为这个TargetLocation
  4. 这样,行为树逻辑就变成了:按顺序执行(Sequence) -> 移动到黑板中TargetLocation存储的位置。

3.3 在蓝图中触发移动

行为树准备好了,但TargetLocation还是空的。我们需要在某个地方设置这个值。通常,这会在AI控制器的蓝图或某个触发器中完成。

打开BP_AI_Controller,我们可以在BeginPlay后,不仅运行行为树,还设置一个初始目标:

  1. Run Behavior Tree节点后,获取Controlled Pawn的位置。
  2. 使用Get Actor Forward Vector和乘法、加法运算,计算一个Pawn前方500单位的位置作为目标。
  3. 使用Set Blackboard Value as Vector节点,将计算出的位置赋值给黑板键TargetLocation(需要先从行为树资源获取黑板组件)。

更常见的做法是响应某个事件。例如,我们可以让AI在感知到玩家后开始追逐:

  1. BP_AI_Controller中,使用OnPossess事件(当控制器占据一个Pawn时触发)来获取并存储该Pawn的引用。
  2. 为AI角色添加一个Pawn Sensing组件,并配置其视觉/听觉范围。
  3. Pawn Sensing组件的OnSeePawn事件中,判断看到的Pawn是否是玩家。如果是,则获取玩家位置,并通过黑板设置TargetLocation。同时,可以在黑板上设置一个Object类型的TargetActor键来存储玩家引用,这样Move To节点也可以直接选择“Blackboard Key”为TargetActor,实现持续追逐。

3.4 移动参数详解与调试

Move To节点和AI Move To函数有很多关键参数,直接影响移动表现:

  • Acceptable Radius:到达距离。当AI与目标点的距离小于此值时,即认为移动完成。对于需要精确到达的场景(如走到某个开关前),可以设小(如50);对于大致区域(如巡逻点),可以设大(如150)。
  • Stop on Overlap:当与目标对象发生重叠时是否停止。追逐玩家时应设为True
  • Use Pathfinding:是否使用路径寻找。当然是True
  • Can Strafe:是否允许侧步。如果AI在移动中需要面向目标(如一边移动一边射击),应设为True,移动组件会计算侧向移动。
  • Allow Partial Path:是否允许使用不完整路径。如果目标点完全不可达,但存在一条能到达“尽可能近”位置的路径,设为True则AI会移动到那个最近点;设为False则移动失败。这是一个非常重要的参数,在动态障碍物阻挡时,设为True可以防止AI完全卡死。

调试技巧

  • 在编辑器中运行游戏时,打开“~”控制台,输入ShowDebug AI,可以在AI角色头上看到其当前行为树状态、黑板值和当前任务。
  • 输入ShowDebug Navigation可以显示实时的路径线。绿色的线是规划路径,AI实际移动时会有一条跟随线。
  • 在行为树编辑器中右键点击,选择“搜索”,输入“Log”,可以添加Log任务节点,用于在行为树执行到特定位置时输出信息,是排查逻辑流程的利器。

4. 高级动态路径规划技术

基础移动能让AI到达静态目标,但真实世界是变化的。玩家可能关门,箱子可能被推倒,其他AI可能挡住去路。这就需要动态路径规划。

4.1 动态避障与路径重规划

UE4的导航系统本身支持一定程度的动态避障,主要通过导航障碍物(Nav Modifier)动态障碍物(Nav Obstacle)实现。

  • 导航障碍物体积:在模式面板的“体积”中,有Nav Modifier Volume。你可以将它放置在场景中,并设置其“区域分类”。例如,设置为“不可行走”,那么这个体积内的NavMesh就会失效,AI会自动绕行。你可以在蓝图中动态设置这个体积的启用(SetActorEnable)来模拟打开/关闭一扇门。
  • 动态障碍物组件:更灵活的方式是为任何需要动态阻挡的Actor添加Nav Obstacle组件。添加后,该Actor就会实时阻挡NavMesh。你可以通过蓝图控制其Set Can Affect Navigation属性。这里有一个关键点:动态障碍物主要影响的是路径的“生成”,而不是路径的“跟随”。也就是说,如果障碍物在AI开始移动后才出现,AI不会自动重新规划路径,除非我们手动触发。

实现路径重规划

  1. 定期重规划:在行为树中,可以在Move To任务的上层(如同一个Sequence中)添加一个Service。这个Service以一定频率(如0.5秒)检查当前路径是否被阻挡。检查方法可以是:从AI当前位置到目标位置做一次Line Trace(射线检测),如果被标记为导航阻挡的物体挡住,则判定为路径受阻。
  2. 触发重规划:当检测到路径受阻时,这个Service可以强制中止当前的Move To任务(通过修改黑板值触发中止条件,或使用Finish Abort装饰器),然后行为树会重新选择执行Move To任务,由于目标未变,它会基于新的环境(包含新障碍物)重新计算一条路径。
  3. 使用AI Move To的观察选项AI Move To节点有一个“Observed Blackboard Value”输入引脚。你可以将一个黑板键(如目标位置)连接到这里。当这个黑板键的值发生变化时,当前的移动任务会自动中止并重新开始,以响应新的目标。这为动态目标提供了内置支持。

4.2 使用EQS进行智能位置选择

当目标不是一个固定点,而是一个需要满足多种条件的“最佳位置”时,Move To就力不从心了。例如,“寻找一个能看到敌人但自己处于掩体后的位置”。这时就需要环境查询系统(EQS)。

  1. 创建EQS查询:在内容浏览器中创建Environment Query资源。EQS编辑器通过生成器(Generators)创建一系列测试点(如在角色周围生成一个网格点),然后通过一系列测试(Tests)对这些点进行评分。
  2. 配置查询:例如,添加一个“Points: Grid”生成器,在AI周围生成网格点。然后添加测试:
    • Trace测试:从每个点到敌人位置做射线检测,能直接看到的点得分高(用于“看到敌人”)。
    • Dot测试:计算每个点与敌人连线的方向,与掩体法线方向的点积,值接近-1(即点在掩体后方)得分高。
    • 最后使用Score测试将多个测试结果加权综合。
  3. 在蓝图中运行EQS:使用Run EQS Query节点执行你创建的查询。它会返回一个位置数组及其得分。
  4. 将结果用于移动:选择得分最高的位置,将其设置为黑板中的TargetLocation,然后由行为树的Move To任务执行移动。

EQS将复杂的位置评估逻辑数据化、可视化,是构建高级AI态势感知和决策的基石。

4.3 局部路径规划与转向行为

有时,全局路径是好的,但AI在跟随路径时移动得很生硬,遇到急转弯会“漂移”或停顿。这涉及到局部路径规划和移动控制。

  • 路径跟随算法AI Move To内部已经实现了基本的路径跟随。但对于非Character的Pawn(如使用浮点移动的物体),你可能需要自己实现。核心逻辑是:获取Navigation Path对象,从中取出路径点数组。让AI朝向并移向下一个路径点,当足够接近时,切换到再下一个点。
  • 平滑转向:在角色移动组件或自定义移动逻辑中,不要瞬间将朝向设置为目标方向。使用RInterp To(旋转插值)或Find Look at Rotation结合Smooth Rotation的方式来渐进地旋转角色,移动会更加自然。
  • 避免静态拥挤:当多个AI需要前往同一区域时,简单的路径规划会导致它们挤在一起。可以在Move To时设置一个较小的Acceptable Radius,并让每个AI在到达后有一个随机的微小位置偏移。更高级的做法是使用NavLink Proxy(导航链接代理)来定义跳跃、攀爬等特殊移动方式,或者使用Crowd Manager(人群管理器)来进行基于速度的避障,但这通常需要更深入的C++集成或插件支持。

5. 性能优化与常见问题排查

一个功能完善的AI系统,还必须考虑性能和稳定性。当场景中有数十上百个AI同时进行路径规划时,优化不当会导致明显的性能卡顿。

5.1 性能优化策略

  1. 降低寻路频率:这是最有效的优化。不要每帧都调用AI Move To或查询路径。
    • 在行为树中,确保Move To任务只在目标改变或路径失效时才被重新执行。
    • 用于检测路径阻塞的Service,其执行间隔(Interval)可以设为0.5秒甚至1秒,而不是0.1秒。
    • 对于巡逻AI,可以在到达一个点后等待几秒,再设置下一个目标。
  2. 简化导航网格:在项目设置(Project Settings)的“导航网格”(Navigation Mesh)部分,调整代理(Agent)的参数。
    • Agent Radius:AI的碰撞半径。在满足 gameplay 需求的前提下,尽可能设置得大一些。较大的半径会让NavMesh在角落处生成更简化的边界,减少网格复杂度。
    • Agent Height:AI的高度。同样,在合理范围内设置。
    • Cell Size:NavMesh网格单元的大小。增加此值会降低寻路精度,但能大幅提升NavMesh生成速度和运行时查询效率。对于大型开放世界,通常需要设置较大的Cell Size
    • 可以为不同体型的AI创建不同的导航代理(Nav Agent),在AI Move To时指定对应的代理,这样大象和小猫就能在不同的网格精度上寻路。
  3. 使用异步寻路AI Move To内部是异步的。但如果你自己调用Find Path to Location Synchronously,它是同步的,可能会阻塞游戏线程。在可能的情况下,使用异步版本(如果有)或将其放入单独的线程/任务中。
  4. 分层寻路(HRA*:对于超大型地图,UE4支持分层寻路。它首先生成一个低精度的“高层”网格用于大区域寻路,再在局部使用高精度网格。这需要在导航系统设置中开启并配置。

5.2 常见问题与解决方案实录

在实际开发中,我踩过不少坑,这里总结几个最常见的问题及其排查思路:

问题一:AI在导航网格边缘“抖动”或无法移动。

  • 现象:AI走到某个位置后开始原地快速旋转或小幅来回移动,控制台显示“Path following failed”。
  • 排查
    1. P键显示导航网格,检查AI所在位置是否在绿色网格边缘或非常靠近障碍物。有时NavMesh生成在复杂几何体旁会有锯齿或空洞。
    2. 检查AI的碰撞胶囊体是否与地面或其他静态网格体有穿透。CharacterMovementComponentHit Z事件可能会被频繁触发,导致移动中断。
  • 解决
    1. 调整场景中静态网格体的碰撞,确保可行走区域是连续的。
    2. 适当增大Move To节点的Acceptable Radius
    3. 在AI蓝图中,检查移动组件是否设置了合理的Ground FrictionBraking Deceleration,过高的值可能导致在微小坡度上无法启动。

问题二:AI无视动态出现的障碍物,直接“穿模”或卡住。

  • 现象:一个箱子被推到路中间,AI依然沿着旧路径移动,要么穿过去,要么在箱子前卡住不动。
  • 排查
    1. 确认动态障碍物Actor是否正确添加了碰撞,并且碰撞预设(Collision Preset)包含了NavigationStaticNavigationDynamic的阻挡响应。
    2. 确认是否添加了Nav Obstacle组件并启用。
    3. 检查行为树是否有路径重规划逻辑(如前面提到的定期检测Service)。
  • 解决
    1. 确保动态障碍物的Can Affect Navigation属性在生成或被推动时为True
    2. 实现路径重规划逻辑。一个简单的方案:在AI身上添加一个定时器,每0.5-1秒执行一次。从AI位置向目标方向发射一条短距离(如AI速度*1秒)的射线检测,如果命中物是导航阻挡,则强制重置移动目标(例如,先将目标设为自身位置,下一帧再设回原目标,以触发重新寻路)。

问题三:多个AI移动时相互卡死,形成“死锁”。

  • 现象:两个AI在狭窄通道迎面相遇,都停下来不动,谁也不让谁。
  • 排查:默认的AI Move To不包含对其他移动AI的避让逻辑。它只考虑导航网格上的静态和动态障碍。
  • 解决
    1. 简单方案:为AI添加一个简单的“避让”行为。在移动Service中,检测前方一定距离内是否有其他AI。如果有,可以让自己短暂停止(Stop Movement)或向侧方移动一小段距离(通过修改移动目标为一个侧向偏移点)。
    2. 使用避让感知:更复杂的方案是使用Avoidance。在CharacterMovementComponent中,可以设置bUseRVOAvoidance为true,并配置Avoidance Consideration Radius等参数。这会让移动组件尝试计算速度障碍来避开其他也启用了避让的AI。注意:这个功能计算开销较大,且需要精细调参,AI数量多时慎用。
    3. Gameplay层解决:从游戏设计上避免,比如设置单向通道,或让AI在相遇时有概率执行一个“靠右走”的偏移逻辑。

问题四:移动动画与实际速度不匹配,出现滑步。

  • 现象:AI的移动动画在播放,但角色模型在原地或移动很慢,看起来像在冰上滑行。
  • 排查
    1. 检查CharacterMovementComponentMax Walk Speed是否设置合理,AI Move To是否应用了期望的速度。
    2. 在动画蓝图中,确保SpeedVelocity变量是从移动组件(Get Velocity)获取的,并且这个速度值被正确地归一化后驱动混合空间(Blend Space)或状态机。
    3. 检查是否有多套动画逻辑在竞争控制角色的位移,例如蓝图中的Add Movement InputAI Move To同时生效。
  • 解决
    1. 确保AI Move To是控制移动的唯一源头。不要在调用AI Move To的同时,还在每帧用Add Movement Input
    2. 在动画蓝图中,使用从移动组件获取的速度向量的长度(Vector Length)来驱动移动动画,而不是用预设的固定值。
    3. 如果使用根骨骼运动(Root Motion)动画,需要确保CharacterMovementComponent中的Movement Mode与动画匹配,并且AI Move To可能与根骨骼运动冲突,需要仔细设计状态切换。

6. 实战案例:构建一个动态巡逻与追击AI

让我们综合运用以上所有知识,构建一个完整的AI示例:它平时在几个点之间随机巡逻,一旦发现玩家,就持续追击,如果玩家躲进房间关上门,AI会在门外徘徊片刻后返回巡逻。

6.1 系统搭建与数据准备

  1. 创建资产:创建BP_AI_Guard(角色)、BP_AI_Guard_Controller(控制器)、BT_Guard(行为树)、BB_Guard(黑板)。
  2. 配置黑板键:在BB_Guard中创建以下键:
    • TargetLocation(Vector): 移动目标位置。
    • PatrolPoints(Vector Array): 存储所有巡逻点的数组。
    • CurrentPatrolIndex(Int): 当前目标巡逻点的索引。
    • HasSeenPlayer(Bool): 是否发现了玩家。
    • PlayerActor(Object): 玩家对象引用。
    • LastKnownPlayerLocation(Vector): 玩家最后被看到的位置。
    • IsInvestigating(Bool): 是否正在调查(如玩家消失后)。
  3. 设置AI角色:为BP_AI_Guard添加PawnSensing组件,配置视觉距离、角度和刷新频率。

6.2 行为树逻辑构建

打开BT_Guard,我们从顶层开始设计:

  1. 根节点:连接一个Selector(选择器)。选择器会执行第一个成功的子节点。
  2. 第一优先级:追击玩家。在Selector下添加一个Sequence,并为其附加一个装饰器Blackboard Based Condition,条件是HasSeenPlayer == True。这个Sequence内部逻辑是“发现玩家后执行的动作序列”。
    • 子任务1:Move To,目标键设为PlayerActor(对象移动)。这样AI会持续追逐玩家当前位置。
    • 子任务2(并行):添加一个Service,名为Update Last Known Location。这个Service以高频率(如0.1秒)运行,只要看到玩家,就将玩家当前位置写入LastKnownPlayerLocation黑板键。同时,在OnSeePawn事件中,我们也要设置这个值。
  3. 第二优先级:调查异常。在Selector下添加第二个Sequence,装饰器条件为IsInvestigating == True
    • 子任务1:Move To,目标键设为LastKnownPlayerLocation
    • 子任务2:Wait,等待2-3秒,模拟观察。
    • 子任务3:Set Blackboard Value,将HasSeenPlayerIsInvestigating都设为False。调查结束,返回巡逻。
  4. 第三优先级:默认巡逻。在Selector下添加第三个Sequence(无需装饰器,作为默认选择)。
    • 子任务1:一个Service,名为Update Patrol Target。这个Service在进入巡逻状态时执行一次,其逻辑是:从PatrolPoints数组中,根据CurrentPatrolIndex取出一个位置,设置为TargetLocation。然后CurrentPatrolIndex自增,如果超过数组长度则归零。
    • 子任务2:Move To,目标键设为TargetLocation
    • 子任务3:Wait,在巡逻点等待一个随机时间(如3-5秒)。

6.3 控制器蓝图中的事件驱动

BP_AI_Guard_Controller中,我们需要响应感知事件来驱动黑板状态。

  1. OnSeePawn事件:当PawnSensing组件看到Pawn时,判断是否为玩家。如果是,则执行:
    • Set Blackboard Value:将HasSeenPlayer设为True
    • Set Blackboard Value:将PlayerActor设为看到的玩家对象。
    • Set Blackboard Value:将IsInvestigating设为False(因为已经直接看到了,无需调查)。
    • Clear Timer:清除一个可能存在的“丢失玩家”计时器(下一步会用到)。
  2. OnPawnLost事件:当玩家离开视线时触发。这里我们不是立即放弃,而是开始一个“调查”流程。
    • Set Blackboard Value:将HasSeenPlayer设为False(因为当前没看到)。
    • Set Blackboard Value:将IsInvestigating设为True
    • Set Timer:设置一个计时器(如5秒),计时器函数里,将IsInvestigating设回False。这样,如果AI在5秒内没有再次看到玩家(通过OnSeePawn事件会清除此计时器),就会结束调查,返回巡逻。

6.4 动态障碍物响应集成

为了让AI能应对关上的门,我们需要:

  1. 为门Actor创建一个蓝图BP_Door
  2. BP_Door中添加Nav Obstacle组件,并设置其Can Affect Navigation属性由一个布尔变量(如bIsOpen)控制。
  3. 在门的交互逻辑中(如被玩家打开/关闭时),更新bIsOpen变量,并相应地设置Nav Obstacle组件的Set Can Affect Navigation
  4. 在AI的巡逻路径上放置这样一扇门。当门关闭时,NavMesh在此处会生成一个动态空洞。AI的Move To任务在下次寻路(或触发重规划)时,会自动绕行。如果AI正在穿过时门关闭,由于我们之前实现了路径阻塞检测(通过Service定期进行射线检测),AI会检测到路径被阻,从而触发重新寻路,它就会寻找新的路线。

6.5 调试与效果微调

将配置好的AI放入关卡,设置好几个巡逻点,并放置一扇门。运行游戏:

  • 初始状态,AI会在巡逻点间移动并等待。
  • 当玩家进入其视野,AI会立即切换为追击状态,行为树选择器执行第一个分支(追击)。
  • 如果玩家跑进房间并关上门,AI会在门口停下(路径被阻)。OnPawnLost事件触发,HasSeenPlayer设为False,IsInvestigating设为True。行为树选择器现在执行第二个分支(调查),AI会移动到玩家最后消失的位置(门口)并等待。
  • 等待期间,如果玩家再次出现(开门),OnSeePawn会触发,清除调查计时器,重置状态,AI继续追击。
  • 如果等待超时(5秒),调查状态结束,AI返回第三个分支(巡逻),从最近的巡逻点继续它的路线。

通过这个案例,你将一个静态的移动指令,升级成了一个具备环境感知、状态记忆、动态决策和异常处理的智能移动系统。整个过程完全由蓝图驱动,无需编写一行C++代码,充分展示了UE4蓝图系统在实现游戏性AI方面的强大与灵活。