第七章

AI 与寻路:让“非玩家角色”自己思考

第六层 · FSM/行为树/A*寻路 峡谷里的小兵、野怪和防御塔“活”了

一、峡谷里的"演员":谁在控制它们

"小陈,峡谷里除了玩家控制的英雄,还有小兵、野怪、防御塔——它们是谁在控制?"老周问。

"AI?"

"对,游戏 AI(Artificial Intelligence)——不过这里的 AI 不是 ChatGPT 那种'智能',是一系列规则脚本,让非玩家角色(NPC)表现出'像人一样'的行为。"

MOBA 里的 AI 角色:
  小兵(Minion):沿着兵线推进,攻击遇到的敌人
  野怪(Monster):在野区巡逻,被攻击后反击
  防御塔(Tower):攻击进入射程的敌人
  泉水/基地:自动恢复、自动出小兵

  每种 AI 的"行为规则"不同:
  小兵:跟着兵线走 → 遇到敌人 → 攻击 → 没血就死
  野怪:在出生点附近徘徊 → 被打 → 反击 → 脱战回血
  塔  :固定位置 → 敌人进射程 → 锁定攻击

"游戏 AI 的本质:'感知 → 决策 → 行动'的循环——每帧看周围情况(感知),决定做什么(决策),然后执行(行动)。规则写得越细,角色看起来越'聪明'。"


二、有限状态机 AI:最简单也最常用

"最简单的 AI 框架:有限状态机(FSM, Finite State Machine)。"老周说,"还记得第四章的动画状态机吗?同一个思想。"

小兵的有限状态机:
  ┌──────────┐   到兵线终点/遇到塔   ┌──────────┐
  │ 前进 Walk │ ──────────────────▶ │ 攻击 Attack│
  └──────────┘                     └──────────┘
      ▲                                │
      │ 目标死亡/脱离                    │
      │                                ▼
      │                             ┌──────────┐
      └─────────────────────────────│ 待机 Idle │
             附近没有敌人             └──────────┘

  每个状态有"进入/更新/退出"逻辑
  状态间靠"条件"跳转

  小兵 AI 伪代码:
  class MinionAI:
      def update(self):
          if self.state == "walk":
              self.move_along_lane()
              if self.find_enemy_in_range():
                  self.change_state("attack")
          elif self.state == "attack":
              self.attack(self.target)
              if not self.target.is_alive():
                  self.change_state("walk")

"FSM 是游戏 AI 的第一课——状态少、逻辑简单、容易调试。小兵、野怪、塔用 FSM 完全够。但复杂角色(BOSS 多阶段技能)状态多了会乱,就需要更高级的框架。"


三、行为树:更高级的 AI 框架

"状态多了以后,FSM 会变成'意大利面条'。这时候用行为树(Behavior Tree)。"老周说:

行为树(Behavior Tree):
  用树状结构组织 AI 行为,从根节点向下"决策"

  野怪的行为树:
  ┌ 选择(Selector:挑一个优先级最高的行为)
  ├── ▶ 逃跑:血量 < 20% 且被追击
  ├── ▶ 反击:正在被攻击
  ├── ▶ 巡逻:没有敌人
  └── ▶ 待机:兜底

  ┌ 节点类型 ┐
  │ 选择器 Selector:试子节点,第一个成功就返回 │
  │ 顺序器 Sequence:全部成功才算成功         │
  │ 条件节点:判断(如"血量 < 20%")          │
  │ 行动节点:执行动作(如"向家移动")          │
  └──────────┘

  好处:
    比 FSM 直观(一眼看清决策逻辑)
    可复用(子行为树可嵌套)
    策划也能看懂、能调

"行为树是商业游戏 AI 的主流框架(Unity 有 Behavior Designer 插件,Unreal 内置)。野怪、BOSS、NPC 队友,都用它。FSM 管'简单角色',行为树管'复杂角色'。"


四、A* 寻路:怎么绕过障碍走到目标

"AI 光会决策还不行,还要会走路——从 A 点走到 B 点,绕过墙和障碍。这就是寻路(Pathfinding),最经典的是 A* 算法。"老周说:

A* 寻路(A-star):
  把地图划分成格子(网格)或导航网格(NavMesh)
  从起点开始,评估每个格子到终点的"代价"
  一步步找出一条"最短路径"

  ┌──┬──┬──┬──┬──┐
  │起 │  │  │  │  │
  ├──┼──┼──┼──┼──┤
  │  │▓▓│▓▓│  │  │   ▓ = 障碍(墙)
  ├──┼──┼──┼──┼──┤
  │  │▓▓│  │  │  │   → = 找到的路径
  ├──┼──┼──┼──┼──┤
  │→→│→→│→→│→ │  │
  ├──┼──┼──┼──┼──┤
  │  │  │  │→ │终│
  └──┴──┴──┴──┴──┘

  A* 核心公式:
    F = G + H
    G = 从起点到当前格子的实际代价
    H = 从当前格子到终点的估算代价(启发式)
    优先扩展 F 最小的格子 → 保证找到最优路径

  工程上:用 Unity 的 NavMesh(导航网格烘焙)
    不用手写 A*,但要知道原理
    (面试常问:A* 的 G 和 H 是什么?)
# A* 的骨架(理解用)
def a_star(start, goal, grid):
    open_set = {start}        # 待探索
    came_from = {}            # 记录路径
    g_score = {start: 0}

    while open_set:
        current = min(open_set, key=lambda p: g_score[p] + heuristic(p, goal))
        if current == goal:
            return reconstruct_path(came_from, current)  # 找到路径
        open_set.remove(current)
        for neighbor in grid.neighbors(current):
            tentative = g_score[current] + 1
            if tentative < g_score.get(neighbor, inf):
                came_from[neighbor] = current
                g_score[neighbor] = tentative
                open_set.add(neighbor)
    return []  # 无路可走

"A* 是'找路'的黄金标准——MOBA 里小兵沿着兵线走、野怪回野区、英雄点击地面移动,背后全是寻路。'点击地面,英雄绕墙走过去',就是 A* 在干活。"


五、塔的攻击逻辑:射程与锁定

"防御塔的 AI 最简单,但有几个经典细节。"老周说:

防御塔 AI 规则:
  感知:扫描射程内的敌人
  决策:锁定"最优先目标"(通常是最近的/攻击友军的)
  行动:发射弹道,造成伤害
  特殊:优先攻击"正在攻击我方英雄"的敌人(保护队友)

  塔的攻击细节:
    射程:攻击半径
    伤害:单体高伤
    冷却:攻击间隔
    索敌:优先最近 / 优先低血量 / 优先攻击我方者

  MOBA 经典机制(简化版可省略):
    塔的"仇恨"机制——攻击谁有讲究
    小兵进塔 → 塔打小兵;英雄攻击敌人 → 塔转移目标
    → 这个"仇恨逻辑"是 MOBA 对线博弈的核心

"防御塔看起来简单,但'仇恨机制'的设计直接决定了对线的体验——高手可以'塔下消耗'、'越塔强杀',全看塔的仇恨规则。这就是'简单角色 + 巧妙规则 = 深度玩法'。"


六、AI 性能与分层更新:别让 AI 拖垮游戏

"峡谷里几十个小兵 + 野怪 + 塔,如果每帧都给所有 AI 做感知决策,性能会炸。"老周说:

AI 性能优化:
  ① 分层更新(最常用):
     - 玩家身边的 AI:每帧更新(精细)
     - 远处的 AI:每 0.5 秒更新一次(粗粒度)
     - 看不到的 AI:暂停更新(等进入视野)
  ② 感知降频:
     不每帧扫描周围,隔几帧扫一次
  ③ 对象池:
     小兵死了不是销毁,是回收复用(第十一章细讲)
  ④ 简化寻路:
     小兵不需要完整 A*,走"预计算的兵线路径"就行

  原则:AI 的"聪明"要花钱(CPU),
        把预算花在玩家看得见的地方

"游戏 AI 的工程原则:'远近有别'——玩家眼前的 AI 要'聪明',远处的可以'迟钝'。把性能预算花在刀刃上,这是老游戏引擎(和手机性能)逼出来的智慧。"


七、章末:老周的第六层总结

第六层:AI 与寻路
├── 游戏 AI = 规则脚本(感知→决策→行动)
├── FSM 状态机:小兵/野怪/塔(简单角色首选)
├── 行为树:复杂角色(BOSS、队友)
├── A* 寻路:F = G + H(找最短路径,绕障碍)
│   工程用 NavMesh,原理要懂(面试必考)
├── 塔仇恨机制:射程+索敌+保护逻辑(对线核心)
└── 性能:分层更新/降频/对象池(钱花在刀刃上)
下一章预告:
  峡谷热闹了:英雄、小兵、野怪、塔都在动。
  但是——这是"单机版"!
  怎么让两个玩家(5v5)在同一局游戏里看到"同一个世界"?
  —— 网络同步。MOBA 最硬核的一章。

"小陈,按一下 Play——峡谷活了!小兵一队队沿着兵线冲,野怪在草丛巡逻,防御塔咚咚地打,好不热闹。"老周满意地笑了,"但是,你现在是'一个人'在打'一堆电脑'。王姐要的是5v5 联网对战——两个玩家在不同手机上,看到的必须是'同一个世界'。下一章,MOBA 最硬核、也是游戏开发里最有含金量的技术:网络同步。"

✌ 语言