docs(workflow): 建立问题管理三段式工作流与经验知识库
- 新增 problem-solving skill:固化「问题分析→工作记录→知识沉淀」9步流程与3模板 - 新建 docs/knowledge/ 经验知识库(README/INDEX/临时方案登记/坑-UE5引擎含2条迁移示例) - GIT-GUIDE 补 §2.7 临时代码 [TEMP-INVESTIGATE] 约定、§2.8 fix 提交引用 issue - CLAUDE.md 项目管理段加问题管理引用 - 配套 Gitea 标签 type:bug / type:investigation(后台已建)
This commit is contained in:
@@ -164,6 +164,28 @@ git commit -m "refactor(inventory): 拆分背包数据层与UI层"
|
||||
- `Binaries/`、`Intermediate/`、`Saved/`、`DerivedDataCache/`
|
||||
- `.vs/`、`*.sln`(由引擎自动生成)
|
||||
|
||||
### 2.7 临时代码与调查脚本(验证完即删)
|
||||
|
||||
排查问题时往往需要写临时验证代码、测试脚本、一次性工具。约定如下(详见 `problem-solving` skill):
|
||||
|
||||
- **默认不进仓库**:临时代码只在本地 / 临时分支跑,验证完删除。
|
||||
- **若必须 commit**(如要在 UE5 里跑):用 `wip` 类型,message 标注 `[TEMP-INVESTIGATE: issue#XX]`,验证后 `git revert` 或删除该 commit。
|
||||
- **文件标记**:文件名前缀 `tmp_` / `dev_`,文件头注释 `// [TEMP-INVESTIGATE: issue#XX] 验证后删除`。
|
||||
- **清理检查**:关闭 issue 前执行 `grep -r "TEMP-INVESTIGATE" Source/ tools/`,确认无残留。
|
||||
- **保留什么**:结论 + 关键代码片段以代码块形式写入 issue 评论,**不保留可运行文件**。
|
||||
|
||||
> 原则:删除的是 artifact,保留的是 insight。
|
||||
|
||||
### 2.8 fix 提交引用 issue
|
||||
|
||||
Bug 修复 / 问题排查类提交,在 body 里引用对应 Gitea issue 号,便于溯源:
|
||||
|
||||
```bash
|
||||
git commit -m "fix(camera): 修复穿墙时摄像机卡顿问题
|
||||
|
||||
issue #42"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 三、版本号规范
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
# 知识库索引
|
||||
|
||||
> 所有经验知识条目一览。**动手改东西前先扫这里。**
|
||||
> 最后更新:2026-07-16
|
||||
|
||||
## 主题文件
|
||||
|
||||
| 文件 | 条目数 | 说明 |
|
||||
|------|--------|------|
|
||||
| [坑-UE5引擎.md](坑-UE5引擎.md) | 2 | UE5 引擎相关:生命周期、初始化时序、API 陷阱 |
|
||||
|
||||
## 全部条目
|
||||
|
||||
### 坑-UE5引擎
|
||||
|
||||
| ID | 标题 | 状态 | 一句话 |
|
||||
|----|------|------|--------|
|
||||
| K-001 | Actor BeginPlay 时序竞争 | ✅正式 | 子系统 Driver 可能晚于 Character 初始化,依赖项要懒创建 |
|
||||
| K-002 | Component Timer/Widget 必须 EndPlay 清理 | ✅正式 | 防 Respawn 野指针崩溃 |
|
||||
|
||||
## 临时方案(技术债)
|
||||
|
||||
详见 [临时方案登记.md](临时方案登记.md)。当前待转正:**0 项**。
|
||||
@@ -0,0 +1,52 @@
|
||||
# 经验知识库
|
||||
|
||||
> ChildHood 项目的「经验知识库」——记录踩过的坑、根因、避坑做法、临时方案。
|
||||
> 与 `docs/` 其他目录的区别:`design/`/`technical/`/`art/` 是**设计知识**(要做什么、怎么设计),本库是**经验知识**(踩过什么坑、怎么避开)。
|
||||
|
||||
## 这是什么
|
||||
|
||||
每次修 bug 或做复杂改动时,**问题分析和修复记录挂在 Gitea issue 上**(事务性,随 issue 归档)。但有些坑值得长期保留——关闭的 issue 不会再被翻,同类坑会反复踩。**本库就是这些长期经验的精选集**。
|
||||
|
||||
只有「会复发的、非显而易见的、值得未来的自己或别人避让的」才进本库。一次性事务不必沉淀。
|
||||
|
||||
## 目录结构
|
||||
|
||||
| 文件 | 用途 |
|
||||
|------|------|
|
||||
| `INDEX.md` | 总索引——所有条目一览,AI/人快速扫描的入口 |
|
||||
| `临时方案登记.md` | 技术债看板——所有「临时方案」集中登记,每条带「何时转正」 |
|
||||
| `坑-<主题>.md` | 按主题归集的坑(`坑-UE5引擎` / `坑-性能` / `坑-美术资产` / `坑-配置`…) |
|
||||
|
||||
## 何时写一条知识条目
|
||||
|
||||
修复一个问题后,问自己(`problem-solving` skill 会自动问):
|
||||
|
||||
- 这个坑**会复发**吗?(换个人、换个系统会不会再踩)
|
||||
- 根因**非显而易见**吗?(光看代码看不出来)
|
||||
- 当前是**临时方案**吗?(需要标记未来转正)
|
||||
|
||||
**任一为是** → 提炼一条进对应主题文件 + 更新 `INDEX.md`。
|
||||
|
||||
## 怎么写(条目模板)
|
||||
|
||||
```
|
||||
### [K-XXX] 标题
|
||||
- 来源: Gitea issue #XX(或 偏差报告 / 审查记录)
|
||||
- 症状: 现象是什么
|
||||
- 根因: 为什么会这样
|
||||
- 避坑做法: 应该怎么做(这是条目的核心价值)
|
||||
- 状态: ✅正式方案 / ⚠️临时方案(预计转正时机:…)
|
||||
- 关联: [[系统-技术方案]]、相关代码位置 file:line
|
||||
```
|
||||
|
||||
- ID 用 `K-001`、`K-002` 递增(全库统一编号,不分主题)。
|
||||
- **临时方案**条目同时登记到 `临时方案登记.md`。
|
||||
|
||||
## 怎么检索
|
||||
|
||||
- **人**:看 `INDEX.md` 一览,或直接翻主题文件。
|
||||
- **AI**:动手改某系统前,先读 `INDEX.md` 判断有没有相关坑。`problem-solving` skill 会自动做这步。
|
||||
|
||||
## 新增主题文件
|
||||
|
||||
坑多了就开新主题文件(如 `坑-性能.md`),命名 `坑-<主题>.md`,并在 `INDEX.md` 的「主题文件」表里登记。
|
||||
@@ -0,0 +1,21 @@
|
||||
# 临时方案登记(技术债看板)
|
||||
|
||||
> 所有「临时方案」集中登记。每条都要写清:**临时在哪、为什么临时、何时/什么条件下转正**。
|
||||
> 定期 review,转正后从这里移除(或标记 ✅已转正留作历史),并同步对应知识库主题文件里的条目状态为 ✅正式方案。
|
||||
|
||||
## 登记表
|
||||
|
||||
| ID | 临时方案 | 位置 | 为什么临时 | 转正条件/时机 | 登记日期 | 状态 |
|
||||
|----|----------|------|------------|----------------|----------|------|
|
||||
| _(暂无)_ | | | | | | |
|
||||
|
||||
## 条目格式(登记时复制)
|
||||
|
||||
```
|
||||
| K-XXX | <一句话描述临时方案> | file:line / 蓝图路径 | <为什么现在只能临时> | <何时/什么条件下转正> | YYYY-MM-DD | ⚠️待转正 |
|
||||
```
|
||||
|
||||
转正流程:
|
||||
1. 把正式实现做掉。
|
||||
2. 在对应主题文件(如 `坑-UE5引擎.md`)的知识条目里,状态改为 `✅正式方案`。
|
||||
3. 回到本表,把该行状态改为 `✅已转正`(保留一行作为历史),或直接删除。
|
||||
@@ -0,0 +1,28 @@
|
||||
# 坑-UE5引擎
|
||||
|
||||
> UE5 引擎相关的坑:Actor/Component 生命周期、初始化时序、引擎 API 陷阱等。
|
||||
> 条目按 ID 排列。新增条目时同步更新 [INDEX.md](INDEX.md)。
|
||||
|
||||
---
|
||||
|
||||
### [K-001] Actor BeginPlay 时序竞争:子系统 Driver 可能晚于 Character 初始化
|
||||
|
||||
- **来源**: P-013 实现偏差报告 · 偏差3
|
||||
- **症状**: 在 `AChildHoodCharacter::BeginPlay` 中通过 `ASystemDriver::Get` 取 Driver,再读子系统(如收集系统)的进度数据时,可能读到未初始化的值(Progress=0、CollectedIDs 空),导致进度 Widget 显示错误或存档恢复失败。
|
||||
- **根因**: UE5 **不保证不同 Actor 的 BeginPlay 执行顺序**。Character 可能先于 `ASystemDriver` 完成 BeginPlay——此时 Driver 虽然存在,但其持有的子系统尚未执行 `RestoreFromPersistence`。
|
||||
- **避坑做法**: 不要在 `BeginPlay` / `Initialize` 里立即创建依赖其他子系统的对象、或读取其状态。改为**首次有效 Tick 时懒创建**——等到 World 完全就绪、依赖子系统完成初始化后再创建/读取。
|
||||
- **状态**: ✅正式方案(已用于 `UCollectionHUDComponent` 的进度 Widget 创建)
|
||||
- **关联**: `docs/technical/收集系统-技术方案.md` §6、`Source/.../CollectionHUDComponent.cpp`
|
||||
|
||||
---
|
||||
|
||||
### [K-002] Component 持有的 Timer / Widget 必须在 EndPlay 清理,防 Respawn 野指针
|
||||
|
||||
- **来源**: P-013 实现偏差报告 · 审查修复2
|
||||
- **症状**: 角色 Respawn(销毁旧 Character、重建新 Character)时崩溃——旧 Component 上还挂着 `SetTimer` 注册的回调,触发时访问已销毁的 UMG Widget,野指针。
|
||||
- **根因**: Component 被销毁时,UE 不会自动清理你手动注册的 `FTimerHandle`,也不会自动移除 `AddToViewport` 的 Widget。这些引用悬挂,下次 Tick 或 Timer 触发即崩。
|
||||
- **避坑做法**: 凡是 Component 持有 `FTimerHandle`(`SetTimer` 注册过)或 `AddToViewport` 的 UMG Widget,**必须 override `EndPlay`**,在里头:
|
||||
- `GetWorld()->GetTimerManager().ClearTimer(MyTimerHandle);`(清所有相关句柄)
|
||||
- `if (MyWidget) MyWidget->RemoveFromParent();`(Widget 还有效则移除)
|
||||
- **状态**: ✅正式方案(项目所有 Character 持有 Component 的卫生写法,保持一致)
|
||||
- **关联**: `Source/.../CollectionHUDComponent.cpp` EndPlay
|
||||
Reference in New Issue
Block a user