# 游戏 AI 系统设计 Confidence: high Last verified: 2026-04-28 Generation: human_only # 游戏 AI 系统设计 > 好的游戏 AI 不是最聪明的,而是**最有趣的**。玩家的乐趣来自可理解、可预测但又充满惊喜的对手行为。 --- ## 目录 1. [AI 设计哲学](#ai-设计哲学) 2. [寻路系统](#寻路系统) 3. [行为树(Behavior Trees)](#行为树behavior-trees) 4. [目标导向行动规划(GOAP)](#目标导向行动规划goap) 5. [效用系统(Utility AI)](#效用系统utility-ai) 6. [群体 AI 与涌现行为](#群体-ai-与涌现行为) 7. [感知与信息模型](#感知与信息模型) 8. [机器学习在游戏 AI 中的应用](#机器学习在游戏-ai-中的应用) 9. [三大引擎 AI 工具对比](#三大引擎-ai-工具对比) 10. [经典案例分析](#经典案例分析) --- ## AI 设计哲学 ### 游戏 AI 与学术 AI 的区别 | 维度 | 学术 AI | 游戏 AI | |------|---------|---------| | **目标** | 最优解 | 有趣的行为 | | **可解释性** | 不重要 | 必须可理解 | | **性能要求** | 可离线计算 | 16ms 内完成 | | **资源限制** | 无限制 | CPU 预算 5-20% | | **容错性** | 零错误 | 偶尔犯错更真实 | | **可预测性** | 避免 | 适度可预测 | ### AI 难度设计 ``` 难度调节维度: ├── 反应速度(Reaction Time) │ └── 简单: 500ms → 困难: 50ms ├── 准确度(Accuracy) │ └── 简单: 30% → 困难: 95% ├── 信息优势(Information) │ └── 简单: 仅视觉 → 困难: 全图知晓 ├── 资源效率(Efficiency) │ └── 简单: 浪费弹药 → 困难: 最优经济 ├── 协作能力(Coordination) │ └── 简单: 单独行动 → 困难: 团队配合 └── 错误率(Error Rate) └── 简单: 频繁犯错 → 困难: 极少失误 ``` ### AI 可玩性原则 | 原则 | 说明 | 反例 | |------|------|------| | **可读性** | 玩家能理解 AI 在做什么 | 瞬移、无动画状态切换 | | **公平感** | AI 似乎遵守同样规则 | 无限弹药、穿墙 | | **个性** | 不同 AI 有不同行为风格 | 所有敌人行为一致 | | **适应性** | AI 对玩家行为有反应 | 无视玩家策略 | | **失误** | 偶尔犯人类会犯的错误 | 完美到不真实 | --- ## 寻路系统 ### 算法对比 | 算法 | 时间复杂度 | 空间复杂度 | 最优性 | 适用场景 | |------|-----------|-----------|--------|----------| | **A\*** | O(E) | O(V) | ✅ | 标准网格寻路 | | **Dijkstra** | O(E + V log V) | O(V) | ✅ | 无启发式统一代价 | | **JPS** | O(E) 实际更快 | O(V) | ✅ | 均匀网格优化 | | **Theta\*** | O(E) | O(V) | 近似 | 任意角度平滑路径 | | **RRT** | O(n log n) | O(n) | 近似 | 高维空间、动态避障 | | **NavMesh** | 预计算 | 预计算 | ✅ | 3D 复杂地形 | ### A* 算法详解 ```python # A* 伪代码 def astar(start, goal, heuristic): open_set = PriorityQueue() open_set.put(start, 0) came_from = {} g_score = {start: 0} f_score = {start: heuristic(start, goal)} while not open_set.empty(): current = open_set.get() if current == goal: return reconstruct_path(came_from, current) for neighbor in neighbors(current): tentative_g = g_score[current] + cost(current, neighbor) if tentative_g < g_score.get(neighbor, INF): came_from[neighbor] = current g_score[neighbor] = tentative_g f_score[neighbor] = tentative_g + heuristic(neighbor, goal) open_set.put(neighbor, f_score[neighbor]) return None # 无路径 # 常见启发式函数 def manhattan(a, b): # 4方向网格 return abs(a.x - b.x) + abs(a.y - b.y) def euclidean(a, b): # 任意方向 return sqrt((a.x - b.x)**2 + (a.y - b.y)**2) def octile(a, b): # 8方向网格 dx, dy = abs(a.x - b.x), abs(a.y - b.y) return max(dx, dy) + (sqrt(2) - 1) * min(dx, dy) ``` ### 高级寻路技术 #### 1. 分层寻路(Hierarchical Pathfinding) ``` 《星际争霸2》寻路层级: Level 1: 战区级别(Region Graph) ├── 将地图划分为连通区域 ├── 区域间预计算连通性 └── 长距离路径:区域图 A* Level 2: 集群级别(Cluster Graph) ├── 区域内部分为网格簇 ├── 簇边界预计算最优路径 └── 中距离路径:簇图 A* Level 3: 网格级别(Tile Grid) ├── 实际可行走网格 └── 短距离/最后阶段:网格 A* 效果:1000x1000 网格寻路从 50ms → <1ms ``` #### 2. 动态避障(RVO / ORCA) ``` RVO2 (Reciprocal Velocity Obstacles): 核心思想: - 每个 agent 选择速度,避免与其他 agent 碰撞 - reciprocal:假设对方也会避让 - 局部最优:只考虑近期可能碰撞的目标 算法: 1. 计算与其他 agent 的速度约束半平面 2. 求解线性规划:在满足所有约束下最接近首选速度 3. 应用新速度 适用:群体移动、人群模拟、RTS 单位移动 ``` #### 3. NavMesh 生成与使用 ``` NavMesh 生成流程: 1. 体素化可行走表面(Voxelization) 2. 识别可行走区域(Walkable Clusters) 3. 构建轮廓(Contour Generation) 4. 简化为凸多边形(Convex Polygons) 5. 构建邻接图(Adjacency Graph) 运行时: - A* 在 NavMesh 图上寻路 - 字符串拉动(String Pulling)优化路径 - 支持动态障碍物(NavMesh Obstacle) ``` --- ## 行为树(Behavior Trees) ### 基础节点类型 ``` 行为树节点分类: 复合节点(Composite) ├── 序列(Sequence)→ 顺序执行,一个失败则全部失败 ├── 选择器(Selector)→ 顺序执行,一个成功则全部成功 ├── 并行(Parallel)→ 同时执行所有子节点 └── 随机选择器(Random Selector)→ 随机顺序尝试 装饰器(Decorator) ├── 反相(Inverter)→ 反转子节点结果 ├── 重复(Repeater)→ 重复执行 N 次或无限 ├── 直到失败(Until Fail)→ 重复直到失败 ├── 冷却(Cooldown)→ 限制执行频率 └── 条件检查(Condition)→ 仅当条件满足才执行 叶节点(Leaf) ├── 动作(Action)→ 执行游戏行为 └── 条件(Condition)→ 检查世界状态 ``` ### 行为树示例:守卫 NPC ``` [Root] Selector ├── [Sequence] 战斗 │ ├── [Condition] 看到敌人? │ ├── [Selector] 选择攻击方式 │ │ ├── [Sequence] 远程攻击 │ │ │ ├── [Condition] 距离 > 5m? │ │ │ └── [Action] 射击 │ │ └── [Sequence] 近战 │ │ ├── [Condition] 距离 ≤ 5m? │ │ └── [Action] 挥砍 │ └── [Action] 追击敌人 ├── [Sequence] 巡逻 │ ├── [Condition] 到达巡逻点? │ ├── [Action] 选择下一个巡逻点 │ └── [Action] 移动到巡逻点 └── [Action] 待机(Idle) ``` ### 行为树与状态机对比 | 特性 | 状态机(FSM) | 行为树(BT) | 推荐场景 | |------|-------------|------------|----------| | **复杂度** | 简单直观 | 需要学习 | 简单 AI → FSM,复杂 AI → BT | | **模块化** | 状态间紧耦合 | 节点可复用 | 模块化要求高 → BT | | **扩展性** | 状态爆炸问题 | 层级组织优雅 | 大量行为 → BT | | **调试** | 直观(当前状态) | 需追踪 tick 路径 | 调试频繁 → FSM | | **性能** | O(1) 状态切换 | O(n) 节点评估 | 性能敏感 → FSM | --- ## 目标导向行动规划(GOAP) ### GOAP 核心概念 ``` GOAP = 状态 + 动作 + 目标 世界状态(World State): ├── hasWeapon: true/false ├── nearEnemy: true/false ├── hasAmmo: true/false ├── health: 0-100 └── ... 动作(Action): ├── 前置条件(Preconditions) │ └── 执行前必须满足的状态 ├── 效果(Effects) │ └── 执行后改变的状态 └── 代价(Cost) └── 时间/资源/风险 目标(Goal): ├── 期望达到的世界状态 ├── 优先级(Priority) └── 可中断性(CanInterrupt) ``` ### GOAP 规划示例 ``` 当前状态:无武器、无弹药、看到敌人 目标:杀死敌人 可用动作: 1. 拾取武器:前提: 武器在附近 → 效果: hasWeapon=true, cost=2 2. 拾取弹药:前提: 弹药在附近, hasWeapon=true → 效果: hasAmmo=true, cost=1 3. 装填:前提: hasWeapon=true, hasAmmo=true → 效果: weaponLoaded=true, cost=1 4. 射击:前提: weaponLoaded=true, nearEnemy=true → 效果: enemyDead=true, cost=1 5. 接近:前提: — → 效果: nearEnemy=true, cost=3 规划器求解: 当前 → 拾取武器 (2) → 拾取弹药 (1) → 装填 (1) → 接近 (3) → 射击 (1) 总代价:8 替代方案: 当前 → 接近 (3) → 近战攻击 (2) → enemyDead 总代价:5 ← 选择此方案(更低代价) ``` ### GOAP vs 行为树 | 维度 | GOAP | 行为树 | |------|------|--------| | **决策方式** | 自动规划 | 手工编排 | | **灵活性** | 高(自动组合动作) | 中(预定义结构) | | **可预测性** | 较低 | 较高 | | **性能** | 规划计算成本高 | 评估成本低 | | **调试** | 难(需理解规划结果) | 易(可视化树结构) | | **典型游戏** | F.E.A.R.、巫师3 | 光环、孤岛危机 | --- ## 效用系统(Utility AI) ### 核心思想 ``` 不同于行为树的"是否做",Utility AI 问"做哪个更好" 每个动作有一个效用函数:Utility = f(世界状态) 选择效用最高的动作执行 效用函数设计: ├── 线性:U = ax + b ├── 曲线:U = x^a(a<1 递减收益,a>1 递增收益) ├── Sigmoid:U = 1 / (1 + e^(-x))(阈值行为) └── 分段:不同区间不同函数 ``` ### 效用系统示例:生存游戏 AI ```python # 效用函数定义 actions = { 'eat_food': { 'hunger_utility': lambda h: 1 - h/100, # 越饿越想吃 'food_available': lambda inv: 1 if inv.food > 0 else 0, 'total': lambda h, inv: (1 - h/100) * (1 if inv.food > 0 else 0) }, 'find_shelter': { 'weather_utility': lambda w: 0.9 if w.storm else 0.1, 'night_utility': lambda t: 0.8 if t > 18 else 0.0, 'health_utility': lambda hp: 1 - hp/100, 'total': lambda w, t, hp: max(w, t, hp * 0.5) }, 'hunt': { 'hunger_utility': lambda h: h/100, 'weapon_utility': lambda inv: 0.9 if inv.weapon else 0.1, 'energy_utility': lambda e: e/100, 'total': lambda h, inv, e: (h/100) * (0.9 if inv.weapon else 0.1) * (e/100) } } # 每帧评估 best_action = max(actions, key=lambda a: a['total'](world_state)) ``` ### Utility AI 高级特性 | 特性 | 说明 | 应用 | |------|------|------| | **衰减** | 上次执行的动作效用暂时降低 | 避免行为切换过快 | | **群体效用** | 考虑其他 AI 的选择 | 分散行为避免扎堆 | | **随机扰动** | 添加小幅随机噪声 | 增加行为多样性 | | **多层选择** | 先选策略,再选具体动作 | 减少每帧计算量 | --- ## 群体 AI 与涌现行为 ### Boids 算法 ```python # Craig Reynolds Boids (1986) class Boid: def update(self, neighbors): separation = self.separate(neighbors) # 避免碰撞 alignment = self.align(neighbors) # 朝向一致 cohesion = self.cohere(neighbors) # 向中心聚集 # 加权组合 self.velocity += (separation * 1.5 + alignment * 1.0 + cohesion * 1.0) self.position += self.velocity # 参数效果 SEPARATION_WEIGHT = 1.5 # 高 → 松散群体,低 → 密集群体 ALIGNMENT_WEIGHT = 1.0 # 高 → 整齐移动,低 → 混乱 COHESION_WEIGHT = 1.0 # 高 → 紧密跟随,低 → 分散 NEIGHBOR_RADIUS = 50 # 感知范围 ``` ### 群体编队 | 阵型 | 实现方式 | 游戏案例 | |------|----------|----------| | **跟随领导** | 每个单位跟随指定路径点 | RTS 行军 | | **网格阵型** | 预定义相对偏移位置 | 全面战争 | | **楔形** | 前方 1 个,后方扇形展开 | 战斗机编队 | | **包围圈** | 围绕目标均匀分布 | 怪物围攻 | | **散兵线** | 横向展开,前后错落 | 射击游戏 | --- ## 感知与信息模型 ### 感官系统 ``` AI 感知模型: 视觉(Vision) ├── 视锥检测(View Frustum) │ └── 角度、距离、遮挡(Raycast) ├── 注意力机制 │ └── 动态物体优先、声音方向提示 └── 记忆衰减 └── 目标离开视野后保留 N 秒 听觉(Hearing) ├── 声音事件(枪声、脚步声、爆炸) ├── 传播范围(距离衰减) └── 方向估计(可能不准确) 触觉(Touch) ├── 碰撞检测 └── 伤害来源方向 社交(Social) ├── 同伴呼叫(发现敌人时通知) └── 状态同步(共享警觉等级) ``` ### 信息层级 | 层级 | 信息确定性 | 行为影响 | 示例 | |------|-----------|----------|------| | **确认** | 100% | 主动攻击 | 视野内清晰看到 | | **怀疑** | 60% | 调查 | 听到声音、看到影子 | | **警戒** | 30% | 准备状态 | 同伴警报、环境异常 | | **正常** | 0% | 日常行为 | 无异常信息 | --- ## 机器学习在游戏 AI 中的应用 ### ML 技术适用场景 | 技术 | 适用场景 | 挑战 | |------|----------|------| | **强化学习(RL)** | 复杂策略游戏、机器人控制 | 训练时间长、不可解释 | | **行为克隆** | 模仿人类玩家行为 | 需要大量标注数据 | | **进化算法** | 平衡性调优、NPC 参数 | 评估函数设计困难 | | **神经网络** | 图像识别(目标检测)、自然语言 | 运行时性能、可预测性 | ### AlphaStar / OpenAI Five 启示 ``` 《星际争霸2》AlphaStar 特点: - APM 限制在 human-level(<300) - 多智能体训练(不同策略种群) - 人口训练(Population-based Training) 《Dota2》OpenAI Five 特点: - 完整 5v5 团队协作 - 奖励塑造(Reward Shaping)关键 - 从随机到世界冠军:约 180 年游戏时间等效训练 应用限制: - 训练成本极高(数百万美元) - 仅适用于规则稳定、可模拟的环境 - 行为不可预测,难以调试 ``` ### 实用 ML 方案 ``` 小规模 ML 在游戏中的实际应用: 1. 难度动态调整 └── 输入:玩家近期表现数据 └── 模型:简单回归或决策树 └── 输出:下一关难度参数 2. 玩家行为预测 └── 预测:玩家接下来可能做什么 └── 应用:预加载资源、AI 提前准备 3. 异常检测 └── 检测:作弊行为模式 └── 模型:无监督聚类 4. 内容推荐 └── 推荐:关卡/装备/技能 └── 模型:协同过滤 ``` --- ## 三大引擎 AI 工具对比 | 功能 | Unity | Unreal Engine | Godot | |------|-------|---------------|-------| | **内置 NavMesh** | ✅ NavMesh | ✅ Recast/Detour | ✅ NavigationServer | | **行为树插件** | ✅ Behavior Designer | ✅ Behavior Tree | ❌ 需第三方 | | **状态机工具** | ✅ Animator FSM | ✅ State Machine | ✅ AnimationTree | | **感知系统** | ❌ 需自写 | ✅ AI Perception | ❌ 需自写 | | **RVO 避障** | ✅ A* Pathfinding Project | ✅ RVO2 | ❌ 需第三方 | | **ML 工具** | ✅ ML-Agents | ✅ Learning Agents | ❌ 不成熟 | | **可视化调试** | ✅ Gizmos | ✅ AI Debug | ✅ 基础 | --- ## 经典案例分析 ### F.E.A.R. — GOAP 标杆 ``` 设计亮点: - 敌人自动规划战术动作 - 可理解的行为(玩家看到 AI 在"思考") - 动态环境利用(踢翻桌子做掩体) - 小队协调(掩护、侧翼、撤退) 规划动作库: ├── 攻击(Attack)→ 前提: 有武器, 看到目标 ├── 寻找掩体(TakeCover)→ 效果: 在掩体后 ├── 侧翼移动(Flank)→ 效果: 目标侧后方 ├── 投掷手雷(ThrowGrenade)→ 前提: 有手雷, 目标在掩体后 └── 呼叫支援(CallBackup)→ 前提: 有通讯设备 ``` ### 光环系列 — 战斗对话系统 | 设计 | 实现 | 效果 | |------|------|------| | **状态广播** | AI 大声喊出当前状态 | 玩家理解 AI 意图 | | **反应对话** | 对玩家行为即时回应 | 增强沉浸感 | | **小队通讯** | 敌人之间喊话协调 | 感觉 AI 在配合 | | **情绪变化** | 从嚣张到恐慌 | 反馈玩家威胁度 | ### 《全面战争》—— 群体战术 AI ``` 战役 AI 层级: ├── 战略层(Strategic) │ └── 目标选择:攻哪座城、结盟/开战 ├── 战役层(Campaign) │ └── 军队调度:行军路线、集结点 └── 战术层(Tactical) └── 战场指挥:阵型、冲锋时机、骑兵迂回 战术决策: - 评估敌我兵力比 → 决定进攻/防守/撤退 - 地形分析 → 高地、森林、河流利用 - 兵种克制 → 骑兵绕后、矛兵抗线、弓箭远程 ``` ### Left 4 Dead — AI Director ``` AI Director 核心循环: 1. 监测玩家压力水平(受伤、弹药、进度速度) 2. 动态生成感染者: - 压力低 → 生成更多敌人 - 压力高 → 生成较少,给予恢复时间 3. 特殊感染者投放时机: - 玩家在开阔地 → 生成 Hunter - 玩家聚集 → 生成 Boomer - 玩家推进快 → 生成 Tank 阻挡 4. 物品放置: - 根据玩家需求动态调整(缺弹药给弹药) 5. 音乐与环境: - 紧张音乐配合生成节奏 ``` --- ## 性能优化指南 | 优化策略 | 具体方法 | 预期收益 | |----------|----------|----------| | **分层更新** | 远处 AI 低频更新(1-5Hz) | 50-80% CPU 节省 | | **睡眠机制** | 不可见/无事件 AI 暂停 | 大量空闲 AI 零开销 | | **空间分区** | 网格/四叉树减少邻居查询 | O(n) → O(log n) | | **路径缓存** | 缓存常见路径 | 减少重复计算 | | ** LOD AI** | 远处 AI 简化决策 | 减少行为树深度 | | **批量评估** | 群体行为统一计算 | 缓存友好 | --- ## 最佳实践清单 - [ ] **从简单开始**:FSM → 行为树 → GOAP/Utility,逐步升级 - [ ] **可调试优先**:AI 决策必须可观察、可记录、可回放 - [ ] **玩家可读性**:AI 行为应有视觉/音频反馈 - [ ] **可控的不可预测**:随机性应可控、可理解 - [ ] **分层架构**:感知 → 决策 → 行动,每层独立测试 - [ ] **性能预算**:AI 每帧 CPU 占用应有明确上限 - [ ] **数据驱动**:行为参数应可配置,避免硬编码 - [ ] **人类测试**:AI 难度和趣味性最终由人类玩家评判 --- ## 相关页面 - [核心机制设计](core-mechanics.md) — 战斗 AI 与机制结合 - [AI Agent 工具](agent-tools.md) — LLM 与游戏 AI 集成 - [AI 对话 Prompt](ai-dialogue-prompts.md) — 叙事 AI 与行为 AI 结合 - [多人游戏设计](multiplayer-game-design.md) — 网络同步与 AI