AI训练3D方块拾取游戏 – 完整开发复盘


AI训练3D方块拾取游戏 – 完整开发复盘

从”假AI”到真正的强化学习,一路踩坑的实战记录

项目周期:2026-05-20 ~ 2026-05-22
作者:Ryan + OpenClaw AI助手


一、项目背景

1.1 初始目标

做一个3D方块拾取游戏,让AI通过强化学习自己学会:

  • 找到方块 → 拾取 → 送到绿色目标区域
  • 没有任何硬编码规则
  • AI通过”眼睛”(视野感知)、”手脚”(移动+拾放)、”奖惩”(反馈机制)自主学习

1.2 技术栈

  • 前端:Three.js (3D渲染) + TensorFlow.js (DQN神经网络)
  • 算法:DQN (Deep Q-Network)
  • 环境:Windows 10, 国内网络(需本地化CDN)

二、开发历程(时间线)

📅 Day 1 (2026-05-20):初版完成,发现根本问题

进展

  • ✅ v1初版完成
  • ✅ 基本玩法:AI移动、拾取方块、送到目标区

问题

  • AI只是执行预设规则,不是真正学习
  • 看起来像AI,实际上是if-else硬编码

决策

放弃硬编码规则,做真正的强化学习

理由:真正的AI应该自己发现策略,而不是执行人写的规则。


📅 Day 2 上午 (2026-05-21):核心机制设计

2.1 视野可扩大机制 (09:52)

决策:视野不是固定的,而是随成功扩大

  • 初始:3×3 视野
  • 每成功配送 +1(最大 9×9)
  • 理由:正反馈循环,AI越做越好,看到的范围越大

2.2 识别奖励稀疏问题 (11:51)

问题:99%状态无反馈,AI学不到东西

分析

  • 只有”配送成功”给+20
  • 其他时候都是0或-0.05
  • 奖励太稀疏,AI不知道自己在进步

规划改进方案:添加渐进奖励(靠近目标时给小奖励)

2.3 Q-Table → DQN 转型 (14:19)

问题:Q-Learning表格法状态空间爆炸

  • 5×5视野 = 25个格子
  • 每个格子多种状态(空/方块/障碍/目标)
  • Q-Table压缩后仍有67.4%无法压缩

决策改用DQN神经网络

  • 输入层:28维状态向量
  • 隐藏层:128 → 64
  • 输出层:9个动作(8方向移动 + 拾放)
  • 经验回放容量:10000
  • 目标网络同步:每100步

理由:状态空间太大,表格法存不下,必须用函数逼近(神经网络)


📅 Day 2 下午 (2026-05-21):调试与优化

2.4 修复CDN链接问题 (14:43)

问题:Three.js/TF.js从CDN加载,国内网络不稳定

解决:下载库文件到本地

  • libs/three.min.js
  • libs/tf.min.js

2.5 定位v6核心bug (15:28)

问题init()定义位置在调用之后,导致初始化失败

解决:改为直接执行,不包装成函数

2.6 训练速度优化 (16:21)

优化

  • 每5步训练一次(而不是每步)
  • 步速调至0ms(无延迟)
  • 超时步数:200步(后来发现太低)

效果:训练速度提升10-12倍

2.7 修复刷分bug (17:27)

问题:已配送的方块没有标记delivered,导致可以重复配送刷分

解决:添加delivered标记,配送后方块消失


📅 Day 3 上午 (2026-05-22):奖励机制反复调试

3.1 问题:AI会卡机制、刷分

现象:每次添加渐进奖励,AI都会找到利用方法刷分,而不真正完成配送

调试过程(多次迭代):

时间添加的奖励AI如何利用结果
17:49探索奖励原地转圈刷探索分删除
17:50空手靠近方块奖励来回走刷分删除
17:59带方块靠近目标渐进奖励在绿色区边缘来回走删除
08:59拾取+3奖励拾取后放下重复刷删除
09:03极简机制采用

3.2 最终极简奖励机制 (09:03)

决策只有配送才给正奖励,其他都是成本或惩罚

每步-0.05 | 撞墙-1 | 配送+20 | 硬捡-0.5 | 太远放下-1

理由

  • 渐进奖励都会被AI利用来刷分
  • 只保留一个明确的目标(配送成功)
  • 让AI自己探索策略,而不是引导它

3.3 修复avgReward虚高问题 (09:24)

问题episodeRewards是扁平列表,每步reward都往里塞,+20直接拉高平均

解决

  • 每步累加到episodeTotalReward
  • episode结束(成功 or 超时)才算一条记录
  • avgReward反映”每局净赚多少”

3.4 DeepSeek建议 + 距离跟踪奖励 (09:39)

DeepSeek建议

  • ✅ 采纳:跟踪方块到目标的距离变化(扛着方块时,近了+0.5/格,远了-0.3/格)
  • ✅ 采纳:拾起/放下同位置惩罚-5(防止AI原地拾放刷分)
  • ❌ 不考虑:动作循环检测(太复杂)、首次拾起+10(太高)、硬终止规则

实现(09:50-10:00):

  • 构造函数添加pickupPoslastCarriedDist
  • 拾取时记录初始距离
  • 移动时跟踪距离变化
  • 放下时检查是否同位置
  • 成功配送后重置追踪变量

📅 Day 3 中午 (2026-05-22):语法错误大作战

3.5 文件损坏与修复 (10:00-11:26)

问题:多次用Node.js脚本编辑HTML,Windows \r\n换行符导致字符串匹配失败

后果

  • 构造函数被重复插入代码
  • executeAction函数结构损坏
  • 界面消失,无法显示

解决

  1. rewrite_func.js一次性重写整个executeAction函数
  2. 验证6/6检查全部通过
  3. 修复大括号/小括号不匹配

教训

  • ❌ 避免多次部分编辑
  • ✅ 一次重写整个函数
  • ✅ 每次编辑后验证括号匹配
  • ✅ 备份第一:copy file.html file.html.bak

3.6 修复agent初始化报错 (11:09)

问题Uncaught ReferenceError: Cannot access 'agent' before initialization

原因resetEpisode()引用agent变量,但agentlet声明,变量提升导致报错

解决

  • let agent = null;var agent = null;
  • 添加安全检查if (!agent) return;

📅 Day 3 下午 (2026-05-22):效率优化

3.7 删除固定时间成本 (11:21)

问题:每步-0.05导致AI积极性低,成功率上升但奖励为负

解决:删除固定时间成本,改用方向引导奖励

  • 空手朝最近方块走:+0.2/格
  • 扛方块朝目标走:+0.5/格
  • 扛方块后退:-0.3/格

效果:奖励变正,AI积极性提高 ✅

3.8 添加进度压力机制 (11:45)

问题:奖励变正后,AI”躺着也赚钱”,不急着完成任务

解决:每50步没配送扣2分

目的:逼AI尽快行动,不要赖着不走

3.9 添加步数效率奖励 (11:52)

问题:进度压力效果不如上一版本

解决步数越少奖励越多

  • 配送基础奖励:+20
  • 效率奖励 = (MAX_STEPS – 实际步数) × 0.1
  • 100步完成 → +70额外 → 总奖励90
  • 700步完成 → +10额外 → 总奖励30

效果:AI拼命找最短路径 ✅

3.10 绿色区域限制 (11:57)

要求:只有放到绿色区域才给奖励,不在区域内再近也不给

解决:修改扛方块移动奖励逻辑

  • 原:if (diff > 0) reward += 0.5 * diff;
  • 新:if (diff > 0 && currDist < 1.5) { reward += 0.5 * diff; }

效果:防止AI在边缘蹭分,必须真正进入绿色区域 👊


三、关键技术决策

3.1 为什么从Q-Learning转到DQN?

特性Q-Learning (表格)DQN (神经网络)
状态空间离散、有限连续、无限
泛化能力有(相似状态共享权重)
内存占用O(状态数×动作数)O(网络参数)
适用场景小规模、离散大规模、连续

本项目:5×5视野 + 携带状态 + 距离信息 = 28维状态向量

  • 表格法:压缩后仍有67.4%无法压缩
  • DQN:用神经网络近似Q函数,解决维度灾难

3.2 为什么奖励机制这么难设计?

核心矛盾任何可度量的中间奖励,都会被AI利用来刷分

案例

  1. 添加”靠近目标渐进奖励” → AI在绿色区边缘来回走刷分
  2. 添加”空手靠近方块奖励” → AI来回走刷分
  3. 添加”探索奖励” → AI原地转圈刷分

最终方案只保留终极目标奖励(配送成功+20),让AI自己探索策略

补充机制

  • 距离跟踪奖励(近了+0.5/格)→ 但有绿色区域限制
  • 步数效率奖励 → 鼓励快速完成
  • 进度压力惩罚 → 防止拖延

3.3 为什么要用经验回放(Experience Replay)?

问题:连续样本高度相关,导致训练不稳定

解决:经验回放缓冲区(容量10000)

  • 存储 (state, action, reward, next_state, done) 五元组
  • 训练时随机采样batch(32条)
  • 好处
  1. 打破样本相关性
  2. 提高数据利用率(一条经验多次使用)
  3. 平滑训练分布

3.4 为什么要用目标网络(Target Network)?

问题:Q网络同时负责行动和评估,容易导致振荡

解决:两个神经网络

  • Q网络(在线网络):负责选择动作
  • Target网络(目标网络):负责评估Q值
  • 每100步同步一次权重

好处

  1. 稳定训练目标
  2. 减少振荡
  3. 提高收敛速度

四、踩过的坑(技术教训)

4.1 Windows换行符 \r\n

问题:用Node.js读文件得到\r\n,但脚本里写\n会匹配失败

案例

// 错误:匹配不到
c = c.replace('hello\nworld', 'hello\r\nworld');

// 正确:用正则或显式指定\r\n
c = c.replace(/hello\nworld/, 'hello\r\nworld');
// 或
c = c.replace('hello\r\nworld', 'new text');

解决方案

  • 脚本里用\r\n匹配
  • 或先统一换行符:c = c.replace(/\r\n/g, '\n')

4.2 多次部分编辑导致文件损坏

问题:多次用脚本部分编辑HTML,导致重复代码、结构损坏

案例

  • 构造函数被重复插入pickupPos = null
  • executeAction函数大括号不匹配
  • 界面消失

解决方案

  • ❌ 避免多次部分编辑
  • ✅ 一次重写整个函数
  • ✅ 每次编辑前备份:copy file.html file.html.bak
  • ✅ 每次编辑后验证括号匹配

4.3 正则表达式匹配到错误位置

问题:用[\s\S]*?贪婪匹配,可能匹配到错误位置

案例

// 错误:可能匹配到文件后面的同名函数
c.replace(/oldFunc[\s\S]*?}/, 'newFunc');

// 正确:更精确的匹配
c.replace(/function oldFunc\(\) \{[\s\S]*?^\}/m, 'function newFunc() {}');

4.4 JavaScript变量提升坑

问题let声明的变量不会提升,在初始化前访问会报错

案例

// 错误
function resetEpisode() {
    agent.xxx; // Uncaught ReferenceError: Cannot access 'agent' before initialization
}
let agent = new DQNAgent();

// 正确
var agent = new DQNAgent(); // var会提升
function resetEpisode() {
    if (!agent) return;
    agent.xxx;
}

五、最终方案(v6 DQN版)

5.1 文件结构

F:\R\R\AI Training\AI V6\
├── ai_v6_dqn.html (主文件)
├── libs\
│   ├── three.min.js
│   └── tf.min.js
└── dqn\
    ├── index.html
    ├── dqn-agent.js
    ├── game-environment.js
    └── *.json (模型文件)

5.2 神经网络结构

输入层:28维
  ├── 5×5视野(25维)
  ├── 是否携带方块(1维)
  ├── 到最近方块距离(1维)
  └── 到目标距离(1维)

隐藏层:128 → 64 (ReLU激活)

输出层:9维(8方向移动 + 拾放)

5.3 完整奖励机制

事件奖励说明
每步移动0无固定时间成本
空手朝方块走+0.2/格方向引导
扛方块朝目标走(绿色区域内)+0.5/格只在dist<1.5时给
扛方块后退-0.3/格鼓励前进
撞墙-1惩罚
硬捡(无方块)-0.5惩罚错误动作
太远放下(dist≥1.5)-1惩罚错误动作
拾放同位置-5防止刷分
配送成功+20 + 效率奖励终极目标
超时空手-10进度压力
超时拿方块-20更重惩罚
每50步未配送-2进度压力

效率奖励 = (MAX_STEPS – 实际步数) × 0.1

5.4 训练参数

epsilon: 0.3,        // 探索率(前期0.5~0.8,后期0.05~0.1)
gamma: 0.99,         // 折扣因子
learningRate: 0.001, // 学习率(前期0.01,后期0.0001)
replayCapacity: 10000,
batchSize: 32,
targetUpdateFreq: 100

六、项目收获

6.1 技术层面

  1. 强化学习奖励设计极其困难
  • 任何可度量的中间奖励都会被AI利用
  • 最好只保留终极目标奖励,让AI自己探索
  1. DQN适合大规模状态空间
  • 表格法只适合小规模、离散状态
  • 神经网络可以泛化到相似状态
  1. 经验回放 + 目标网络是DQN标配
  • 稳定训练
  • 提高数据利用率

6.2 工程层面

  1. 文件编辑要谨慎
  • 备份第一
  • 避免多次部分编辑
  • 验证括号匹配
  1. Windows环境特殊坑
  • \r\n换行符
  • 路径分隔符\
  • 需要本地化CDN
  1. 调试工具很重要
  • 括号匹配检查脚本
  • 代码结构验证
  • 控制台日志

6.3 产品层面

  1. AI训练需要耐心
  • 前期avgReward为负很正常
  • 要观察几百episode才能看到趋势
  1. 成功率比奖励更重要
  • 奖励可以调整
  • 成功率反映真实能力
  1. 用户反馈驱动迭代
  • 老大多次提出机制问题
  • 每次调整都让AI更智能

七、未来优化方向

7.1 算法层面

  • [ ] Prioritized Experience Replay:优先回放重要样本
  • [ ] Dueling DQN:分离状态价值和优势函数
  • [ ] A3C/A2C:异步优势演员-评论家(更适合连续动作)

7.2 环境层面

  • [ ] 动态障碍物:增加难度
  • [ ] 多个方块:排序配送
  • [ ] 更大地图:9×9 → 15×15

7.3 可视化层面

  • [ ] 训练曲线实时绘制(TensorBoard)
  • [ ] AI决策过程可视化(Q值热力图)
  • [ ] 对比不同版本性能

八、总结

这个项目从”假AI”(硬编码规则)到真正的强化学习,经历了:

  1. 技术选型:Q-Learning → DQN
  2. 奖励机制:多次迭代,最终极简
  3. 工程调试:语法错误、文件损坏、环境兼容
  4. 效果优化:进度压力、效率奖励、绿色区域限制

核心教训

真正的AI不是写出来的,是训练出来的。奖励机制设计比算法选择更重要。

当前状态

  • ✅ avgReward为正数
  • ✅ 成功率持续上升
  • ✅ AI学会高效配送策略

下一步

  • 继续训练观察稳定性
  • 定期保存”AI大脑”
  • 尝试更难的地图

项目仓库F:\R\R\AI Training\AI V6\ai_v6_dqn.html

在线演示:https://ryanren.top/ (待部署)


写于 2026-05-22,济南
Ryan + OpenClaw AI助手 联合创作

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注