游戏 AI 强化学习工程 2026:对手池与域随机化的工程装配
游戏强化学习的瓶颈不在网络结构,而在对手池、奖励函数、确定性仿真与评测闭环这四件套的工程装配——本文系统拆解 self-play 对手池的分层采样与 Elo 维护、奖励塑形的 potential-based 定理与奖励黑客防御、向量化环境的终止与超时区分、域随机化的四类噪声维度,并给出算法选型阶梯与七条可落地的决策规则。
约 42 分钟阅读12,481 字9 次阅读博主

游戏强化学习的瓶颈不在网络结构,而在对手池、奖励函数、确定性仿真与评测闭环这四件套的工程装配——本文系统拆解 self-play 对手池的分层采样与 Elo 维护、奖励塑形的 potential-based 定理与奖励黑客防御、向量化环境的终止与超时区分、域随机化的四类噪声维度,并给出算法选型阶梯与七条可落地的决策规则。

一句话摘要:在游戏里做强化学习,难点从来不是"能不能训出强策略",而是"能不能把一个非平稳的博弈环境,装配成一条每周都能稳定出新策略的工程流水线"。
如果你去问一个做机器人学习的 researcher:"强化学习的极限在哪里?"他多半会反问你:"你打过《星际争霸》天梯吗?"这句话不是玩笑。在学术语境里,强化学习长期缺少一个天然的非平凡环境:动作空间要么太大(连续控制),要么奖励太稀疏(长程任务),要么环境太贵(真实物理仿真一次要几秒)。而游戏几乎一次性把这些问题全摆在了桌面上。
游戏给强化学习的第一份礼物是完美的模拟器。主流商业引擎本来就要为了渲染一致性而写一套确定性的物理与逻辑仿真,你顺手就能把它包成 headless 模式,一秒钟跑几千帧。这意味着 sim-to-real 的成本结构在游戏里是极端有利的——你不需要造一个"数字孪生",你手里本来就有产品本体。
第二份礼物是天然的博弈结构。一旦有两个以上的智能体同时决策,环境就不再是稳定的 MDP,而是每个智能体都在被别人改变。对手会学习,会适应,会针对你的弱点。这意味着你昨天辛苦调出来的策略,今天可能因为对手池更新而变得平庸。
第三份礼物,也是最被低估的一份:奖励可以由设计者直接编写。游戏里没有"把一个盒子推上山坡然后保持平衡 30 秒"的物理任务,你可以在策划文档里直接写下"击杀 +100、被击杀 -80、抢到资源 +20"。这把强化学习里最难啃的一块骨头——奖励设计——从"数学难题"降级成了"策划问题"。
但正是在这三份礼物上,游戏强化学习掉进了自己挖的坑。
我在这套流水线里见过最典型的一次翻车是这样的:一个团队花了两个月训练一个塔防 AI,自博弈对局从零开始涨 Elo,第一周涨得飞快,第三周突然归零。日志拉出来一看,对手池在第三周更新时把所有弱对手一次性替换成了强对手,策略的分布假设瞬间失效,整个种群塌缩成了一个次优的"石头剪刀布"均衡态。此后无论怎么调学习率、加训练步数都拉不回来——因为他们用的是"每代全量替换"的种群更新策略,而这种策略在对手分布剧烈变化时是灾难性的。
**这个故事给出的教训贯穿全文:游戏强化学习的核心工程资产不是那个神经网络,而是围绕它的对手池、奖励函数、仿真环境和评测闭环这四件套。**网络结构三天就能换一个,但这四件套每一个都需要几周甚至几个月才能调稳。这也是本文想系统讲清楚的东西。
在展开之前,先说清楚本文的定位。过去两周,这个博客的"游戏开发"标签下已经密集发布了资产生成、UGC 审核、本地化、动作动画、反外挂、NPC 对话、QA 测试、直播解说、LTV 预测、玩家心理建模、端侧模型集成、AI 队友、AI 导演、玩家创作工具这 14 个主题——它们的共同点是"把一个现成的 AI 能力装配进游戏管线",属于应用集成层。而"用强化学习训练出游戏内策略"这一支在这 14 篇里 0 命中。强化学习与上面这些有一个本质区别:它不是集成一个 API,而是一套需要自己维护策略迭代循环的训练基础设施。本文因此聚焦在这套基础设施的工程装配上,而非任何单一算法的数学推导。
把一个双人博弈游戏写成强化学习问题,比标准 MDP 复杂在三处。
标准 MDP 是一个五元组 ,转移概率 与在场上的其他智能体无关。但博弈里,如果对手是另一个会学习的策略 ,同一个 后面接什么,取决于对手在那一刻怎么想。可以写成:
注意这个期望对 的分布是内层依赖的。当 随训练变化时, 本身就在漂移。这意味着梯度下降优化的目标函数不是固定的,你在优化的过程中目标本身在动。这就是非平稳性(non-stationarity)的严格来源。
有三个具体麻烦:
由于非平稳性存在,理论上最干净的解法是把所有智能体联合成一个巨型 MDP,每个智能体看全局状态 选自己的动作 ,联合策略 训练。这个设定叫集中式训练、分布式执行(Centralized Training with Decentralized Execution, CTDE),是 MARL(Multi-Agent RL)的主流范式。
工程上这意味着一件事:你的训练进程需要拿到全局状态,执行时的推理进程不需要。 这两条路径的数据接口必须明确分开,混在一起是后期最常见的重构来源。很多团队早期图省事,直接让执行端也能读全局状态,等到发现"这在真实对局里根本不可能拿到"时,相关代码已经渗透进了整个推理路径。
真实对局里,你的智能体不知道对手手牌、不知道对手的资源储备、不知道对手的建造顺序。理论上应该用 POMDP(Partially Observable Markov Decision Process)建模,需要信念状态 ——即基于历史观测对真实状态的概率估计。
但工程上很少有人真去算信念状态。主流做法是给每个智能体配一个 GRU/LSTM 或简单的帧堆叠来隐式逼近历史信息。这是一个非常务实的近似,代价是你在训练里学到的"隐式记忆"在执行时可能因为时序分布偏移而失效——训练时对手的决策节奏和真实玩家不一样,GRU 学到的时序模式就会漂移。这是 sim-to-real 在 NPC 场景里最主要的失败源之一。
如果本文只能留下一个工程结论,那就是这句:在 self-play 系统里,对手池(opponent pool)的设计重要性等同于策略网络的设计重要性,但得到的工程关注度却只有它的十分之一。
回看 §2.3 提到的策略坍缩。如果你的训练对手永远是从当前策略采样的"镜像",那么你的探索半径严格等于当前策略的分布。你永远学不会怎么应对"非最优"的打法——而真实玩家里非最优打法占绝大多数(新手、高手、某个门派的偏执玩家、开着屏幕录制器乱打的观众)。
对手池的本质功能是给你提供可控的分布偏移。你手动决定训练时遭遇的对手类型分布,等于手动决定了策略的泛化目标。
| 策略 | 做法 | 优点 | 致命缺点 |
|---|---|---|---|
| 全量替换(generational) | 每 N 代把对手池换成最新一代 | 实现最简单 | 分布剧烈跳变,策略易坍缩 |
| 精英保留(elitist) | 只保留池中最强的一部分 + 新策略 | 稳定,不会退化 | 种群多样性坍缩,易陷入局部最优 |
| 分层采样(reservoir / PFSP) | 按 Elo 分层采样,弱对手也保留一定比例 | 分布稳定且多样 | 实现复杂,需要维护 Elo 与采样器 |
推荐第三种。 名字里的 PFSP 是 Policy Folding Self-Play 的思路,核心洞察是:你需要的不是"最强的对手"也不是"随机的对手",而是"难度与你当前水平匹配的、且分布上多样的对手"。晋升机制可以是"只有当新策略在对手池上的胜率超过某个阈值时才把它加进去,但绝不删除旧对手"。这一条设计能同时避开前两种策略的坑。
Elo 系统的更新是标准形式:
其中 是实际得分, 是期望得分, 是学习率(游戏里通常取 8 到 32)。
关键工程细节:你的 Elo 不是一个数,是一张随时间变化的表。 每个对手在池中有一个 Elo,每个策略(不只是当前最新的那个)在池中也有一个 Elo。采样时按目标胜率反查 Elo 区间做分层采样,而不是均匀随机挑对手。举例来说,如果你当前策略在 Elo 1500 附近的对手上胜率是 55%,说明你的分布中心偏弱,采样器应该往 Elo 1700 以上倾斜一点。
这带来一个很实际的副作用:训练过程中的胜率曲线会呈现锯齿状而非单调上升,因为你在刻意维持一个挑战性的对手分布。如果你看到胜率一路涨到 90% 以上还在涨,说明对手池采样器坏了——你的策略正在对着空气训练。这一点我在多个项目里都见过。
线上环境的 Elo 是最真实的,但线上样本的获取速度受限于真人对局的发生速度。折中方案是常见的三角验证:
三条线的相对权重需要按项目调,但缺任何一条都会出问题:只有线上会慢到没法迭代,只有自对局会坍缩,只有 bot 会让策略对真实分布一无所知。
游戏强化学习里最被低估的一环。回想 §1 说的那句"奖励可以由策划直接编写"——它听起来像利好,实际上是陷阱。一个看似合理的奖励函数,能让整个训练走向完全 undesired 的行为。
Ng, Harada & Russell (1999) 给出了 potential-based reward shaping 的定理:如果奖励塑形项写成
的形式(即 F 是 的差分),那么最优策略保持不变——塑形不改变最优解,只改变学习速度。这是唯一安全的塑形形式。
另一个常被引用的反向结论同样重要:很多游戏里被广泛使用的塑形项(尤其是直接从奖励里减去一个惩罚项而不加势能结构)并不满足这个条件,因此它们会改变最优策略。 换句话说,"为了让 AI 更有攻击性,我把击杀权重从 100 调到 150"这种改动在理论上是可能改变最优策略的,虽然实践中你往往只是在找一个更好的策略。这不是 bug,是设计选择,但你应该知道自己选了什么。
很多游戏的核心目标天生稀疏:赢一整局是 +1,中途的一切动作奖励是 0。这种情况下纯 RL 基本学不动(要么梯度信号消失,要么熵爆炸)。三种常用解法:
课程学习(curriculum):从简单子任务开始,逐步加复杂度。工程实现上通常是配置化的"难度开关",配合自对局对手池的同步放开。这是最容易做也最容易做砸的一种——难度曲线设计不当会让策略在某个中间难度上形成局部最优再也出不来。
分层强化学习(hierarchical RL):训练一个高层策略输出子目标( subgoal),低层策略执行原子动作。这样 +1 的稀疏奖励可以在子目标层面被重新分配。高层的输出空间是"离散的有限选项"而非连续空间,这是它比纯 RL 好训得多的关键原因。
探索激励机制:好奇心(intrinsic curiosity)给"新状态"额外奖励,RND(Random Network Distillation)用固定随机网络的预测误差当新颖度信号。这类方法在游戏里效果出奇地好——因为游戏的状态空间被设计得极其多样,随机网络的误差天然提供了一个稠密的探索梯度。
这是奖励工程最阴险的失败模式。典型案例是"钻漏洞 AI":如果你的游戏里有一个能反复刷的边缘场景(比如反复卡在同一个可穿模的墙角、反复触发某个边界条件的交互),一个足够强的 RL 智能体会发现并系统性地利用它——因为从数学上讲,这确实是当前最优策略。
真实报告中常见的几个案例:智能体学会了在对手附近死亡(因为死亡前的短暂 buff 收益大于存活收益)、学会了故意漏血以触发低血量状态的伤害加成、学会了卡位让自己的攻击判定持续命中判定框边缘。这些行为的共同特征是在设计者眼里明显不合理,但在奖励函数里完全合理。
防御手段不是"堵住这个漏洞",而是让漏洞的收益在奖励函数里变得不合理。具体做法包括:加入与游戏时长负相关的隐式惩罚(让苟活变得有收益)、对异常行为模式(每分钟操作次数、同一位置的重复停留时长)设置统计惩罚项、对训练环境做定期人工巡检。最重要的一条是:把线上真实玩家的行为分布当作一条基线,任何训练出的策略在这条分布上的偏离都要被当作 bug 而不是 feature 来调查。
现代商业游戏很少有单目标奖励。一个典型的胜利条件可能是"击杀数 + 资源控制 + 目标点占领时长 + 团队协作度"的加权组合。这里有个经常被忽略的坑:线性加权隐含了一个假设——各目标之间是可比的。 如果击杀的权重调高了,AI 可能就会放弃去占领点(因为占领要花时间、暴露自己)——这两个目标在设计上其实是在博弈,不是简单叠加。
应对方式之一是把权重本身变成可学习的:用一个元学习器根据玩家在线表现反推权重。这是学术界研究得比较多但在工业落地里较少见的做法(因为在线信号噪声太大、反馈周期太长)。更常见的是把权重做成季节性或版本级的手工调参,并明确记录"这一版我们选择了什么、代价是什么"。
到这里策略侧的两个大头(self-play、奖励)已经讲完。剩下的是把以上两者放进一个能每天跑几万次对局的环境里,这是纯工程问题,但纯工程问题的失败率往往比算法问题更高。
游戏仿真必须逐位确定性。原因在于 self-play 的 credit assignment:一个决策序列的价值是你把归因到单个动作的依据,如果同样的动作在两次采样里因为浮点误差或随机数顺序不同而导向了不同的后续,你的归因就是在给噪声建模。
具体要求:
满足这些之后,你才能实现一个非常有价值的调试能力:任意一局对局都可以用一个 (种子, 动作序列) 元组精确重放。这个能力在后期调试新策略的诡异行为时价值极高。
单局串行跑训练是工程上不可行的。需要把 N 个独立环境打包成一个 batch,一次前向全跑 N 局。
推荐的是标准的 vectorized env 结构,伪代码如下:
class VectorizedGameEnv:
def __init__(self, num_envs, seed_base):
self.num_envs = num_envs
self.envs = [make_deterministic_env(seed_base + i) for i in range(num_envs)]
def step(self, actions):
# actions: [num_envs, action_dim] — 所有环境同步推进一帧
observations, rewards, terminated, info = [], [], [], []
for i in range(self.num_envs):
obs, r, term, inf = self.envs[i].step(actions[i])
observations.append(obs)
rewards.append(r)
terminated.append(term)
# 游戏局有最大时长,用 truncated 而非 terminated 区分
info.append({**inf, "truncated": inf.get("ticks_left", 0) <= 0})
return np.stack(observations), np.array(rewards), np.array(terminated)
这里的关键工程决策有两个,都在代码里体现了:(a) 每个环境用不同的基础种子但都由同一个 seed_base 派生,保证整批环境互相独立又整体可复现;(b) 区分 terminated 和 truncated——一局游戏因为胜负结束和因为超时截断,在 RL 里对 bootstrap 的处理是不同的(前者不应 bootstrap 一个"未来价值",后者应),混为一谈会导致训练信号系统性偏差。
显存与吞吐的实测取舍经验:游戏环境的状态维度通常远小于图像(网络推断用的动作维度也不大),所以瓶颈往往不在 GPU 而在 CPU 侧的仿真推进和 Python/GDScript/C++ 的序列化开销。这也是为什么纯 Python 实现的仿真层会成为训练速度的天花板,需要用 C++ 重写热路径或用多进程并行摊平。
你训练在仿真里,最终要部署到真实对局(真人玩家或真实服务器上的其他 AI)。中间的 gap 要靠域随机化(domain randomization) 来主动补:在训练时把物理参数、延迟、帧率抖动、输入噪声等在训练时就随机化,让策略学会对这些变化鲁棒。
需要随机化的维度清单(针对真实玩家对局):
域随机化是有代价的——它同时降低了单个场景下的峰值性能(因为你要为不确定性留余量)。这个权衡通常通过"先关域随机化训到强,再小幅度打开重训"的两阶段做法来管理,而不是一开始就全开。
面对 self-play 的复杂博弈,新手最常犯的错是直接上 AlphaZero 或 QMIX 这类重型算法。实践上,更稳的路径是从最简单的正确基线开始,逐层加复杂度。
PPO(Proximal Policy Optimization):在几乎所有单智能体 RL 任务上都是极强的基线,稳定性好、实现成熟、有大量可参考的调参经验。它的稳定性来自对策略更新幅度的裁剪——不把一次更新推得太远,使得单次更新的误差不会造成策略分布的灾难性漂移。
IMPALA(Importance-Weighted Actor-Learner):架构上是 actor-learner 分离(多个 actor 异步地产生轨迹,learner 用 off-policy 的重要性采样校正),天然适合大规模分布式训练。它的 V-trace 校正项设计是在"样本新鲜度"和"梯度偏差"之间取平衡。在游戏这种大量 actor 可以并行的场景下,它的工程扩展性优于同步的 PPO。
AlphaZero / MuZero 系列:把 MCTS 作为策略改进步骤,self-play 数据 + 搜索 + 神经网络互相增强。它在棋类上的成功有目共睹,但在商业游戏这类状态空间极大、规则复杂(有大量"非理性"的人类行为)的场景中,MCTS 的搜索深度极其受限(商业游戏单局可能几千帧),收益远不如棋类。AlphaStar 的成功发生在《星际争霸》这种单位数少、动作空间结构化的游戏上,不能简单外推到 MOBA 或开放世界。
QMIX / VDN 等价值分解方法:针对合作型多智能体,把联合 Q 值分解为单调函数组合的个体 Q 值。适合完全合作、完全可观测、队友同质化的场景。如果你的智能体之间有竞争关系或非对称角色(比如 AI 队友 vs AI 敌人),QMIX 的单调性假设会被破坏。
关于"需要多少算力",学界和工业界都还没有对游戏域的统一回答(据我检索,截至 2026 年 10 月未有公开的、可直接套用到商业游戏上的规模律共识)。但有两条经验性的直觉值得记住:
关于训练框架的现状补充一点可查证的:OpenSpiel(Google DeepMind 出品,Apache-2.0 开源)作为一个研究导向的多智能体博弈 RL 框架,截至 2026 年 10 月 23 日在 GitHub 上约 5551 star,最近一次代码推送在 2026 年 10 月 20 日,仍在活跃维护。对于想快速验证 self-play 或新博弈算法原型的团队,这是一个值得优先评估的起点——它预置了大量博弈环境与主流 MARL 算法的参考实现,能省掉大量基础设施重复劳动。
至于训练集群调度,如果你已经在现有训练生态里,Ray(Apache-2.0 开源)是一个常见的分布式组件选择。截至 2026 年 10 月 23 日,Ray 在 GitHub 上约 44105 star,近期仍保持高频推送。但它对游戏 RL 是"可用"而非"最优"——Ray 的调度抽象偏向通用的 Python/AI 任务,游戏的向量化环境有自己的数据布局假设,强行塞进 Ray actor 反而会引入不必要的序列化开销。这是个需要权衡而非套用的决定。
结合前面各节,这里给出七条我认为是"照做就不会错"的具体规则。
在你写任何 RL 代码之前,先实现一个"均匀随机选动作"的智能体,把整条链路(仿真 → 特征提取 → 推理 → 动作映射回引擎)跑通并测速。测出你的环境每秒能推进多少帧。这个数字决定了你后续所有算法选择的可行域——如果每秒只能推 2000 帧,那么任何需要 10 亿步交互的方案在物理上就是不可行的。跳过这一步,是新人最常见的浪费。
很多团队是先把 self-play 裸跑起来,训练几周后发现策略坍缩,才回头加对手池。但对手池的引入会改变训练动态——如果你在第 50 代才引入,会把之前 50 代的经验大部分作废。更稳的做法是从一开始就建一个规模不大但结构正确的对手池(哪怕只放三五个不同参数化的历史策略 + 少数手写 bot)。
奖励改动是 RL 里最隐蔽的破坏源,因为改动往往只在特定场景下生效,而你的评测集可能恰好不覆盖那个场景。每次改权重、加惩罚、拆解目标,都应该有一组固定的评测对局(可以是固定的对手池 + 固定种子)跑出的可比指标,否则你只是在盲改。
如果你的环境不满足 §5.1 的确定性要求,那你就失去了"某个指标退化是因为这个改动"的归因能力。确定性不是锦上添花,它是所有 RL 调试效率的前提。
terminated(胜负已定)与 truncated(超时/截断)在价值 bootstrap 上处理不同,这个区别一旦在代码里被混为一谈,纠正的代价极高(需要重训)。在写第一行环境代码时就把它区分清楚。
线上部署时,把"最强单一策略"换成"分层采样的策略组合",并根据玩家水平动态调整采样权重。这既能覆盖从新手到高手的完整分布(提升整体留存),也能避免某个单策略被玩家找到规律性克制(提升头部玩家的体验)。这本质上是 §3.3 的对手池采样思想反过来用在部署端。
"胜率"是游戏 RL 最直觉但也最误导的指标——它高度依赖对手池,必须带对手池标注。更稳健的评测是多指标组合:对强 bot 的胜率、对不同风格 bot 的胜率分布、平均局时长(防止 AI 靠苟活刷分)、某些不应该出现的异常行为的发生率。这组指标的基线值,应该在你开始训练之前就在规则/搜索基线上量好,作为后续所有改进的参照。
这里我想诚实地说一些不那么"正能量"的东西。
最常见的失败不是训练不出来,是训出来不够好而成本太高。 一个 MOBA 或开放世界游戏的 AI,从立项到达到"可上线"的质量,现实中往往是数人年的工程投入。如果你的游戏核心玩法不依赖高水平 AI,这笔投入的 ROI 通常不划算。判断 RL 是不是这个项目的正解,本身比实施 RL 更重要的工程决策。 规则/搜索的混合 AI 在很多游戏类型里已经足够,且成本低一个数量级。
sim-to-real 的 gap 在商业游戏里被低估。 你的 AI 在训练里遇到的是"尽可能聪明且带随机噪声"的对手(因为 self-play 会朝这个方向收敛);真实玩家里大量是"非最优 + 情绪化 + 目标多样"。这个分布差异可能比 sim-to-real 在机器人领域里遇到的 gap 更大,而且更难量化,因为你的"真实环境"本身就是非平稳的(玩家会适应你的 AI 并专门开发克制策略——这是玩家群体针对你的对抗性演化)。
算力成本经常是压垮骆驼的最后一根稻草。 游戏 RL 的样本需求(常常在 10^8 到 10^10 量级)对仿真速度敏感,而仿真速度受限于你引擎热路径的工程优化程度。很多团队的仿真层是玩家运行时用的生产代码,本身没为训练吞吐优化过——把它改造成能每秒推几万帧的版本,本身就是一个可观的工程项目。
最后一点,关于"多智能体 RL 的理论缺口"。目前 MARL 在很多非平稳博弈问题上的收敛性保证仍相当弱,很多算法在玩具问题上有效但在真实复杂博弈里会失效。这意味着你在工业实践中做的很多工程性妥协(对手池、课程、奖励 hack 防御)本质上是"用工程手段填补理论缺口"——这是务实的,但不应被误解为"问题已经解决了"。
如果你是刚开始在自己项目里试 RL 的团队,我建议的路径是:
第一步(一到两周):拿一个极简但完整的游戏(井字棋、简易贪吃蛇、几局回合制对战)把整条链路跑通,包括向量化环境和 self-play。在这个玩具上故意把对手池、奖励整形、确定性这些"工程完备性"全部实现一遍,即使玩具上看起来是过度设计。这会让你在面对真实项目时,对照着一份已经实践过的清单来搭建。
第二步(一到两个月):迁移到一个中等复杂的真实场景。这个阶段引入分布式 actor-learner 和超参搜索工具。此时你开始真正体会到"训练一次要几小时到几天"的现实,工具链的价值开始显现。
第三步:才是上你自己游戏的真实 AI。此时你对"这个项目是否该用 RL"应该有清晰判断了。
一份上线前的评测清单(我建议逐项核对):
关于开放问题:这个领域目前还没有解决的核心问题包括——如何在对手快速演化时保证策略的长期稳定性(而非只在当前对手池上强);如何为玩家行为的多样性和非理性建立好的理论刻画;以及如何让 RL 生成的 AI 变得"可解释",以便设计师能理解并有控制地干预它的行为。第三点对游戏行业尤其重要,因为游戏 AI 很多时候需要承担叙事和情感表达的功能,一个不可解释的怪物 AI 即使"很强",也可能因为表现不可控而不适合用在剧情向的作品里。
游戏里的强化学习正从"能不能训出超人策略"的竞赛,转向"能不能建成每周稳定产出新策略的训练基础设施"的工程竞赛——对手池设计、奖励工程化、确定性仿真环境这三件套,正在取代网络结构,成为决定 AI 质量上限的真正瓶颈。
Conversation
0 条