救命!修完49个BUG后,我终于教会AI不重复踩坑了(附经验库展示
精华修改于03/10396 浏览开发心得 包含 AI 合成内容
作者:浠涫
项目:节拍前夜 (Beat Eve) — Roguelike × 节奏 × 回合策略
引擎:TapTap Maker (UrhoX)
BUG 库版本:v4.7 / 49 个 BUG / 56 个经验模式
前言:依旧是那句:同一个坑,你愿意踩几次?
AI 写代码效率极高,但有一个致命缺点——不长记性。
上周修了一个“backgroundImage 不继承父级 opacity”的 BUG,这周让 AI 写新的屏幕切换动画,它又犯了一模一样的错;你告诉它“Lua 5.4 的 string.format 不能用 %d 格式化浮点数”,下次它还是会写出 string.format(""%d"", slider.value)。
在 1 个月的快速开发周期中,我累计修复 49 个 BUG,并从中提炼出 56 条“经验模式”,构建了结构化的 BUG 经验库。AI 每次开工前读取一遍,可以避免犯同类错误。
本文核心分享:经验库的组织方法、标准化记录格式,以及从 49 个真实 BUG 中提炼的 10 个高价值经验模式,全程干货,可直接复用至你的 AI 协作开发项目。
提示:本文 BUG 经验库可与 AI 记忆文档、相关 Skill(如 read-memory-docs、update-memory-docs)配合使用,实现“记录-读取-自动规避”闭环,最大化减少 AI 重复踩坑,提升开发效率。
第一章:经验库的结构设计
经验库建议采用纯文本文件(如 BUG修复经验.txt),便于 AI 快速读取和维护,当前版本约 2500 行,整体分为三个核心部分,结构清晰、适配 AI 解析习惯:
Part 1:快速索引(按类别):按 BUG 类型分组,每行标注 BUG 编号和一句话描述,方便 AI 快速定位相关问题;
Part 2:详细记录(每个 BUG 一个章节):记录单个 BUG 的完整信息,包括现象、根因、修复方案和核心教训;
Part 3:经验模式总结(提炼通用教训):从多个同类 BUG 中提炼通用规则,实现“一次记录,终身避坑”。
1.1 快速索引设计
将所有 BUG 按类别分组,索引格式简洁明了,示例如下:
【UI/交互类】
BUG-0 Modal.Confirm 弹窗卡死 → 用标准 Modal
BUG-1c 按钮创建时视觉未同步 disabled → Create 末尾手动同步
BUG-32 装备面板悬停检测偏移一格 → translateX 不影响 hit-test
【节拍/跟拍类】
BUG-1 跟拍乱按无惩罚 → 三状态判定机制
BUG-3 漏拍后连锁抢拍 → missCooldown 0.3s
【种子/确定性类】
BUG-P5.2-1 pairs() 非确定性迭代 → 收集键 → sort → ipairs
建议按项目实际场景划分类别,本文案例中累计分为 15 个类别,AI 接到任务后,可先扫描索引找到相关类别,再跳转至详细记录阅读,大幅提升效率。
Skill 配合提示:可将经验库的快速索引同步至 AI 记忆文档,配置 read-memory-docs Skill 时,设置“优先读取索引-匹配类别-调取详细记录”的逻辑,让 AI 快速定位相关经验,无需逐行读取全文。
1.2 类别体系(可直接复用)
类别无需预先定义,随 BUG 积累自然涌现。当某个类别累积 3 个以上 BUG 时,说明该领域是“事故高发区”,需重点关注。以下是 1 个月开发中总结的 15 个类别及核心信息,适配 TapTap Maker + Lua 开发场景:

第二章:单条 BUG 记录格式(标准化可复用)
为保证经验库的规范性和可复用性,每个 BUG 需采用统一记录格式,核心聚焦“可落地、可复用”,无需冗余信息,格式如下:
BUG-XX: 标题(一句话描述问题)
严重度: 🔴 严重 / 🟡 中等 / 🟢 轻微
影响范围: 涉及的模块/屏幕
现象:(用户看到了什么,客观描述,不添加主观判断)
根因:(代码层面的核心错误,明确 AI 犯错的关键原因)
修复方案:(具体可落地的修改步骤,AI 可直接参考)
教训:(提炼通用经验,避免同类错误重复出现,核心重点)
其中,“教训”是整个记录的核心,直接决定经验库的价值。举个真实案例:
BUG-6 教训:
❌ nvgFillColor(nvg, r, g, b, a) — 这不是合法的调用方式!
✅ nvgFillColor(nvg, nvgRGBA(r, g, b, a))
对比其他能正常渲染的 Widget 确认正确用法。
这条教训后来被提炼为“经验模式 7”,AI 后续编写任何 NanoVG 代码时,都会自动使用正确的颜色 API 调用方式,彻底杜绝同类错误。
记忆文档配合提示:建议将“经验模式”单独整理成精简版,同步至 AI 记忆文档核心区域,让 AI 无需打开完整经验库,即可快速调取核心规则;同时可关联相关 BUG 详细记录,便于 AI 追溯细节。
第三章:经验模式——从个案到通则(10 个高价值模式)
“教训”是针对单个 BUG 的具体总结,“经验模式”则是从多个同类 BUG 中提炼的通用规则,可覆盖更多场景、预防变体错误。注:以下模式基于本人项目真实 BUG 提炼,核心规则通用可复用,项目专属细节已补充解读,读者可重点关注“规则+通用场景”,快速套用。
经验模式的统一格式:
【模式 N: 标题】
一句话规则(核心结论,AI 可快速抓取)
典型错误示例(明确 AI 常犯的错误写法)
正确做法(可直接复用的代码/逻辑)
关联 BUG 编号(便于追溯原始案例,非项目内用户可忽略)
以下是 1 个月开发中提炼的 10 个高价值模式,覆盖 UI、渲染、跨平台、Lua 语法等高频踩坑领域,可直接复制给你的嗒啦啦参考:
模式 21: backgroundImage opacity 不继承父级
⚠️ 规则:UrhoX UI 的 backgroundImage 渲染不受父元素 opacity 影响(通用场景:所有基于 UrhoX 引擎的 UI 开发,涉及图片背景+透明度控制均适用)。
关联 BUG:BUG-15(战斗屏幕淡出时按钮图标残留)、BUG-33(地图屏幕切换闪烁)、BUG-40(更多元素残留)(项目专属案例,核心问题是“屏幕切换时元素残留”,通用场景可参考)
正确做法:
- 普通 UI Widget → 跟随父级 opacity,不需要额外处理(通用可复用)
- backgroundImage → 必须直接 SetStyle({ opacity = 0 })(UrhoX 引擎专属正确写法,直接复用)
- NanoVG Widget → 必须用 SetEnabled(false)(UrhoX 引擎 NanoVG 组件通用写法)
模式 29: 两阶段状态操作之间的竞态窗口
⚠️ 规则:当一个操作分两个时间点执行(阶段 1 设置标志,阶段 2 消费标志并清理),必须考虑外部事件在两阶段之间修改了前提条件的情况(通用场景:所有涉及“状态设置-状态清理”的异步操作、多系统交互场景均适用)。
关联 BUG:BUG-24(教学战斗 inputBlocked 死锁)(项目专属案例,本质是“状态清理不及时导致死锁”,通用场景可参考)
错误原因:70ms 的竞态窗口内,其他系统消费了待处理的状态,导致清理逻辑永远不执行 → 永久死锁(通用解读:异步操作中,两阶段间隔内,外部因素可能改变状态,导致清理逻辑失效,引发死锁、数据异常等问题)。
正确做法:(通用可复用,所有两阶段状态操作均适用)
1. 阶段 2 失败时提供清理逻辑
2. 在更高层级(回合开始、页面初始化等)添加清理守卫
3. 设置超时兜底,避免不可逆死锁
模式 35: WASM 中 Lua userdata 不等于有效 C++ 对象
⚠️ 规则:在 WASM 运行时,C++ 引擎对象被释放后,Lua userdata 仍然存在(~= nil 检查通过),但访问属性触发 memory access out of bounds 崩溃(通用场景:所有 Lua + C++ 混合开发、涉及 WASM 跨平台部署的项目均适用)。
关联 BUG:BUG-30(手机端随机崩溃)(项目专属案例,核心问题是“跨平台对象释放后引用残留”,通用场景可参考)
错误原因:AudioManager 每帧访问 bgmHandle_.source.timePosition,应用切后台时 C++ 对象被释放,再次访问即崩溃(通用解读:跨平台场景中,引擎对象释放后,脚本层引用未清理,继续访问会导致崩溃)。
正确做法:(通用可复用,所有 Lua + C++ + WASM 开发均适用)pcall 探测性读取一个轻量属性(如 .gain),失败则判定对象已释放,清理所有 Lua 侧引用。
模式 46: PLL 解耦时钟——视觉与音频分离
⚠️ 规则:音频时钟天然不稳定(10-20ms 更新间隔),视觉时钟应独立运行,通过速率微调柔性追踪,永不跳变(通用场景:所有涉及音频与视觉同步的项目,如节奏游戏、音视频交互项目均适用)。
关联 BUG:BUG-28、BUG-39、BUG-39b、BUG-39c(节奏动画顿挫、回弹)(项目专属案例,核心问题是“音画不同步”,通用场景可参考)
正确做法:(通用可复用,所有音画同步场景均适用)参考节奏地牢(Crypt of the NecroDancer)“动画与音乐分离”思路,采用 PLL 解耦时钟,±2% 的速率变化人眼完全不可感知,避免位置跳变。
模式 49: 平台容器篡改引擎回调参数
⚠️ 规则:嵌入式容器环境(如 TapTap iOS 容器、小程序容器等)可能修改引擎的回调参数值(通用场景:所有需要嵌入第三方容器、跨平台部署的项目均适用)。
关联 BUG:BUG-42(iOS 上全游戏速度减半)(项目专属案例,核心问题是“容器篡改参数导致运行异常”,通用场景可参考)
错误原因:eventData["TimeStep"] 的值被容器减半,所有动画、倒计时、节拍系统都变慢(通用解读:第三方容器可能拦截引擎回调,修改关键参数,导致项目运行速度、逻辑异常)。
正确做法:(通用可复用,所有容器嵌入、跨平台开发均适用)用 time:GetElapsedTime() 作为独立时钟交叉验证,仅在检测到异常时切换到兜底值。
模式 50: 跨生命周期持久化 Widget 的 Detach-before-Destroy
⚠️ 规则:当一个 Widget 需要跨 UI 树持久化时,必须在旧 UI 树销毁前 Detach(移除但不销毁)(通用场景:所有涉及 UI 树切换、Widget 持久化的 UI 开发均适用)。
关联 BUG:BUG-43(PerfMonitor 跨屏幕切换必崩)(项目专属案例,核心问题是“Widget 跨生命周期引用残留”,通用场景可参考)
错误原因:Destroy 递归销毁旧 root 时连带释放了 PerfMonitor 的 Yoga 节点,但 Lua 侧引用仍存在 → use-after-free(通用解读:UI 树销毁时会递归释放子节点,若 Widget 需跨 UI 树复用,未提前移除会导致引用失效,引发崩溃)。
模式 51: Lua 5.4 禁止 string.format("%d", float)
⚠️ 规则:永远不要用 %d 格式化浮点数,永远用 %.0f(通用场景:所有 Lua 5.4 版本开发的项目,涉及数值格式化均适用,是 Lua 语法高频踩坑点)。
关联 BUG:BUG-44(第 3 次出现同类错误)(项目专属案例,核心问题是“Lua 语法使用错误”,通用场景可直接复用规则)
错误原因:Slider 返回值、JSON 解码值、除法结果都是 float,即使数值看起来是整数(270.0),类型仍然是 float,用 %d 会导致崩溃(通用解读:Lua 5.4 中,%d 仅支持整数,浮点数需用 %.0f 格式化,否则会触发崩溃)。
模式 53: 修改前必须验证代码是否在活跃执行路径上
⚠️ 规则:修改文件前,必须先确认该文件确实是运行时活跃代码(通用场景:所有项目迭代、代码维护场景均适用,尤其适合多版本文件共存的项目)。
关联 BUG:BUG-46(5 次修改全部白费)(项目专属案例,核心问题是“修改了非活跃代码,做无用功”,通用场景可参考)
错误原因:连续 5 个会话修改 RhythmTrackV2.lua 的判定文字,但实际运行的是 RhythmTrackV3.lua + BattleTextFX.lua(通用解读:项目迭代中,可能存在多版本文件,若未确认文件是否被引用就修改,会导致修改无效,浪费开发时间)。
正确做法:(通用可复用,所有代码修改场景均适用)从入口文件追溯调用链,确认目标文件确实被使用。
模式 55: pointerEvents="none" 是子树级屏蔽
⚠️ 规则:pointerEvents="none" 会跳过整棵子树的命中测试,不仅仅屏蔽自身(通用场景:所有涉及 UI 交互屏蔽的开发,如覆盖层、弹窗遮罩等场景均适用)。
关联 BUG:BUG-48(UIEditOverlay 覆盖层无法交互)(项目专属案例,核心问题是“交互屏蔽范围理解错误”,通用场景可直接复用规则)
错误原因:overlay 作为 bgWidget_ 的子节点,而 bgWidget_ 设了 pointerEvents="none",导致 overlay 永远收不到事件(通用解读:pointerEvents="none" 会作用于自身及所有子节点,若仅需屏蔽自身,需单独设置子节点的交互属性)。
模式 56: 高频回调中禁止同步 I/O
⚠️ 规则:Slider/拖拽等每帧触发的回调中,绝对不能有同步磁盘 I/O(通用场景:所有涉及高频回调、磁盘操作的开发,如编辑器、实时交互组件等场景均适用)。
关联 BUG:BUG-49(材质编辑器滑块延迟)(项目专属案例,核心问题是“高频回调中同步 I/O 导致卡顿”,通用场景可参考)
错误原因:每帧 Slider.onChange → UMC.set() → cjson.encode → File.Write,在移动端主线程被磁盘 I/O 阻塞(通用解读:高频回调(每帧触发)执行同步 I/O 会阻塞主线程,导致界面卡顿、交互延迟,尤其在移动端更为明显)。
正确做法:(通用可复用,所有高频回调场景均适用)高频修改 → 内存缓存 + 版本号递增 → 显式保存时落盘。
第四章:如何建设自己的 BUG 经验库(5 步速成)
无需复杂搭建,跟随以下 5 步,即可快速建立自己的 BUG 经验库,适配 1 个月快速开发节奏,让 AI 彻底告别重复踩坑:
Step 1:确定记录格式(直接复用)
核心保留 4 个必选字段,其余字段可按需添加,兼顾简洁性和实用性:
- 现象:用户看到的客观表现(便于 AI 匹配当前问题)
- 根因:代码层面的错误原因(明确 AI 犯错核心)
- 修复方案:具体修改步骤(可直接落地)
- 教训:通用经验(核心,避免重复踩坑)
可选字段:严重度、影响范围(便于分类管理)。
Step 2:把握记录时机(关键)
修完一个 BUG 立即记录,不要等积累后补录——补录会遗漏关键细节,降低经验库价值。
高效技巧:通过 AI 自动化工具(如 update-memory-docs Skill),让 AI 修复 BUG 后,自动在经验库追加记录,若有通用教训,同步提炼为经验模式,节省手动记录时间。
Skill 实操提示:配置 update-memory-docs Skill 时,可绑定经验库文件路径和记忆文档同步规则,设置“修复 BUG 后自动追加记录+提炼模式+同步至记忆文档”,实现经验库与记忆文档实时联动,无需手动同步。
Step 3:定期归纳模式
每积累 5-10 个 BUG,花 10 分钟回顾,重点提炼两类模式:
- 同类 BUG 反复出现 → 提炼为通用模式(如 opacity 不继承相关 BUG);
- 跨类别的共性问题 → 提炼为更高层级的模式(如状态管理类通用规则)。
Step 4:让 AI 主动读取
经验库写了不读 = 没写。配置 AI 读取工具(如 read-memory-docs Skill),让 AI 在处理 BUG 类任务时,自动读取经验库,匹配当前问题与已知模式,主动规避错误。
记忆文档+Skill 配合提示:可在记忆文档中设置“BUG 经验匹配触发条件”,当 AI 接收到 BUG 修复、代码编写任务时,read-memory-docs Skill 自动触发,读取经验库和记忆文档中的相关模式,主动规避同类错误,无需手动指令。
Step 5:持续维护迭代
经验库不是一次性文档,需随项目迭代更新:
- 新增重大 BUG 或新模式时,更新版本号和变更记录;
- 项目迭代后,删除过时的 BUG 记录(如旧版本引擎相关错误);
- 补充新的经验模式,逐步完善覆盖范围。
第五章:经验模式的分类统计(精准避坑)
我的56 个经验模式按领域分布如下,可重点关注高频踩坑领域,提前做好预防:

关键结论:UI/渲染和状态管理加起来占比近 40%,是 TapTap Maker + Lua 开发中最容易踩坑的领域,建议重点完善这两类经验模式。
第六章:经验库的 ROI(为什么值得投入)
维护一个 2500 行的 BUG 经验库需要投入少量时间,但它是 AI 协作开发中 ROI 最高的环节,核心原因有 3 点:
1. 节省 BUG 修复时间:BUG 修复是最痛苦的开发环节,一个竞态类 BUG 可能消耗 2-5 轮对话,经验库可彻底避免重复踩坑,省下大量时间;
2. 经验可举一反三:一个模式能预防多种变体错误,如模式 21(opacity 不继承),不仅适用于 backgroundImage,还推广到 NanoVG Widget 和 DMPanel;
3. 适配 AI 强项:AI 擅长模式匹配,人类可能忘记“上次怎么解决的”,但 AI 读取经验库后,能精准匹配当前问题与已知模式,彻底发挥 AI 优势。
总结
BUG 经验库的核心理念:每个 BUG 只允许出现一次。修复后立即记录教训,提炼为可复用的经验模式,让 AI 在未来开发中自动规避同类问题,实现“一次投入,终身受益”。
从 0 到 1 落地建议(适配短开发节奏):
1. 下次修完 BUG 后,花 5 分钟记录现象 + 根因 + 教训;
2. 积累 5 个 BUG 后,回顾提炼 2-3 个通用模式;
3. 配置 AI 工具,让 AI 处理 BUG 时自动读取经验库;
4. 持续迭代,享受“AI 不再重复犯错”的高效开发体验。
核心配合提示:经验库、记忆文档、Skill 三者联动是关键——经验库提供完整案例和模式,记忆文档提供精简核心规则,Skill 实现自动化读取和同步,三者配合可彻底解决 AI 不长记性的问题,大幅提升 AI 协作开发效率。#TapTapmaker #开发心得 #节拍前夜 #TapTapmaker #bug




