① 架构概览
AIController + BehaviorTree + Blackboard + 蓝图派生 Pawn + AI 子蓝图。
AI 敌人的 Pawn 不是独立新建的,而是角色蓝图派生的子蓝图(保留完整角色 Mesh / 动画 / 蒙太奇 / 技能图表,只改控制器和输入属性)。整套 AI 由 6 个核心资产 + 4 个攻击扩展资产组成:
| 资产 | 职责 |
CharacterEnemyBlueprint(子蓝图) | AIControllerClass=EnemyAIController;AutoPossessPlayer=Disabled(关键,不能让 PIE 里玩家控制器抢占);Tags += "Enemy" |
EnemyAIController | RunBehaviorTree 入口;OnPossess 时写黑板(HomeLocation / bEngaged=false) |
EnemyBehaviorTree | Selector 调度三个分支(回家/战斗追击/待机),服务 0.5s 检测 |
EnemyBlackboard | 黑板键:bEngaged、bWantsAttack、DistanceToTarget、HomeLocation、TargetActor |
EnemyCombatActionTask(BTTask) | 执行攻击动作:普攻五连蒙太奇 / 闪电技能 / 瞬移飞行 |
EnemyTargetService(BTService) | 每 0.5s 刷新 DistanceToTarget、掷骰 bEngaged 黏性锁定 |
导航系统:关卡原本 NavMeshBoundsVolume 未启用(enable_navigation_system=False)。本任务顺带启用并新建 30000×30000×2000 的大体积(tile=11163),否则 AI MoveTo 不可用。
② 行为树结构
Selector 单根,三个分支左→右优先级递减。
Root └ Selector【服务 EnemyTargetService,Interval=0.5,挂根层 ⇒ 待机时也检测】 ├ 分支1 回家 │ ├ 装饰器:DistanceToTarget > 35000(cm = 350m) │ │ FlowAbortMode=Both:真→抢占下面所有分支;假→放弃本分支 │ ├ MoveTo:HomeLocation,AcceptableRadius=300 │ └ Wait 2.0 ├ 分支2 战斗/追击 │ ├ 装饰器:bEngaged 为 true(Abort=LowerPriority) │ └ Selector │ ├ 攻击序列 │ │ ├ 装饰器:bWantsAttack 为 true(抢占追击 MoveTo) │ │ └ EnemyCombatActionTask │ └ MoveTo:TargetActor,AcceptableRadius=600(追击) └ 分支3 待机:Wait 3.0
关键机制。bEngaged 是黏性的——进 100m 就锁定为 true,只有 >350m 才解除(避免敌人在边缘反复切换)。bWantsAttack 由 EnemyTargetService 掷骰(Random < 0.35 且冷却完毕)写入,解决"追击 MoveTo 常驻运行会饿死攻击分支"的经典问题。EnemyCombatActionTask 开头必须立刻清掉 bWantsAttack=false,否则冷却门形同虚设。
③ 战斗决策逻辑(距离段分档)
EnemyCombatActionTask 按距离自动选择动作;总闸冷却 4~8s 防止 AI 刷屏。
| 距离段 | 候选动作 | 实现 | 冷却 |
| < 1500cm(15m) | 普攻五连 | 调角色蓝图事件 → 顺序播 13_combo_1~5 五段蒙太奇;每段 0.25s 出追踪弹(EnemyTrackBullet,归航 6000、伤害 20);ApplyDamage 只对 GetPlayerPawn(0)、距离≤60m(绝不追/伤敌人蓝图) | 3~6s |
| 1500~5000 | 闪电技能 → 普攻 | 播 04_beam_all(无伤害,纯表演)→ 等 1s → 接普攻 | 10~15s |
| 5000~15000 | 瞬移 → 飞行 | 瞬移=播瞬移蒙太奇 + ProjectPointToNavigation(必须判成功布尔,失败→不位移)+ SetActorLocation;飞行=MOVE_Flying + Launch(0,0,500) 悬 3.5s 后 MOVE_Falling | 8~12s / 20~30s |
④ 遁光追击 + 玩家命中(2026-09-29 ~ 10-01 新增)
四项扩展,PIE 实测全绿;①②③ 实装,④ 护盾格挡待人肉确认。
| 扩展 | 实现 |
| 遁光追击(AI 版右键遁光) | C++ 新增 ExecuteEnterTransformForAI / ExecuteExitTransformForAI(CharacterTransformBase 的 BlueprintCallable,完整复刻玩家右键遁光时序:溶解 0.2s→闪光→0.4s→进遁光态;退出反向)。BTTask EnemyDashChaseTask 调 Enter → 直线追击(4500cm/s,set 位置+Sweep)→ ≤12m → 调 Exit → 轮询等待退出完成(bIsInTransformedForm==false,1.5s 超时兜底)→ 就绪后写 bWantsAttack=true |
| 五连完整普攻 | EnemyCombatActionTask 顺序播 1~5 蒙太奇(每段 0.25s 出 1 发追踪弹),5 段完 SetAttackCooldowns(now+4~7s) |
| 玩家可命中 AI | AI 必须"可被剑气/Q键六剑/普攻/闪电 命中"。泛化方式:新建接口 EnemyTargetInterface(FakerHP / CanTick / LightningPick / CE_LightningLink),EnemyBlueprint(原无人机)与 CharacterEnemyBlueprint 均实现;复制三个 Tag 版攻击资产(BezierBullet_TagEnemy/SwordBullet_TagEnemy/Lightning_Branch_TagEnemy,索敌改 Actor Has Tag("Enemy"));玩家 Attack 图 2 处 SpawnActor 指向副本。原资产零改动(无人机行为零回归) |
| 护盾格挡 | 子弹 ProjectileCollision Block on WorldDynamic → 撞护盾产生 Hit 被挡。护盾侧=E键护盾(Tick 轮询物理 E 键),自动化无法注入键鼠,待人肉按 E 验证 |
⑤ 实测踩坑(全部 PIE 端到端验证)
- 关卡导航系统原本禁用(
enable_navigation_system=False+ NullNavSysConfig)——旧的 100×100m NavMeshBoundsVolume 从未生效过。本任务顺带启用并新加了大体积。 - 角色蓝图继承的
AutoPossessPlayer=Player0会让 PIE 里玩家控制器抢占这个 Pawn。子蓝图必须设AutoPossessPlayer=Disabled,否则 AI 根本不由 AIC 控制。 - OnPossess 必须 RunBehaviorTree 之后再写黑板:先写黑板时黑板尚未装配,写入静默丢失(运行时读到 FLT_MAX)。
- 追击 MoveTo 常驻运行会饿死同层左侧的攻击分支(行为树不会重搜已激活分支)→ 引入 bWantsAttack 黑板键 + 装饰器 Abort=LowerPriority 抢占;且 BTTask 必须在执行开头清掉该键,否则冷却门变成唯一节流,攻击频率暴增且掷骰失效。
- TransformBase 的 CharacterMovement 默认
DefaultLandMovementMode=MOVE_Flying(继承类悬浮形态默认)——AI 直接持有时出生即 Flying、永不落地,加上飞行动作 Launch 后无重力刹不住 → 悬空 44m"隐形"。修法:AI 子蓝图 BeginPlay 强制SetMovementMode(Walking)(PIE 105s 验证 C++ 不会打回)。 - 瞬移动作两层坑:① ProjectPointToNavigation 失败返回零向量,必须接成功布尔分支(失败→Finish(false));② 玩家 Pawn 出界被销毁时 GetPlayerPawn=None,读位置得零向量 → 投影到原点"成功"→ 传送到 (0,0,0)。位置源必须判有效性。
- BTTask 同步 FinishExecute 会饿死 ReceiveTickAI:攻击分支原先"执行完立刻 Finish"→ Tick 从不运行 → 0.4s 命中判定是死代码。任务型动作必须靠 ActionDuration 计时走到点再 Finish。
- 角色蓝图内置伤害管线只认 DroneTarget(
EF_BP_BezierBullet的 BeginOverlap 且 OtherActor==DroneTarget)——原角色是打无人机的,伤不到玩家 pawn。AI 的伤害必须自己 ApplyDamage(现方案:只对 GetPlayerPawn(0),距离≤6000,天然满足"只对角色产生伤害、不伤 EnemyBlueprint")。 - 限频真凶:出弹源从不写冷却变量(探针实测该值冻结 26 秒)→ 入口闸形同虚设 → 21 发/秒打崩 GPU。修=出弹后 SetAttackCooldowns(现 4~7s)。排查手段:加临时 Print 探针实测各链路计数,不要靠推断。
- 遁光中攻击 + 退出特效不出:①到达链 Exit 后同帧写攻击意愿,攻击抢在 0.1+0.4s 过渡前;②玩家距 12~18m 时到达落在进入过渡窗口(0.4s)内,Exit 被 C++ 守卫吞掉(日志 SKIPPED 实锤)→ 卡遁光。修=等待退出阶段(轮询+重试+超时兜底)+ CombatAction 入口双保险。
AI 敌人系统主资产 6 个 + 攻击扩展资产 4 个 + C++ 新增 2 个接口函数(h:419-432 / cpp:962-1026)。回滚=删所有新蓝图资产 + 删 C++ ForAI 接口。角色蓝图本体零改动。