Files
zeling_v2/Docs/Review/DeepDive_2026_Q2.md
2026-05-12 15:34:08 +08:00

161 lines
8.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 代码深度评审 DeepDive 2026 Q2
> 评审范围:`Assets/Scripts/` 416 个 .cs 文件DeepDive_2026.md 修复完成后的新一轮评审)
> 重点模块Audio、Camera、Dialogue、Quest、Progression、EventChain、UI、Tutorial、World全子系统、Support
> 评审标准以商业级成熟作品Hollow Knight、Celeste、Hades为参照基线
---
## 一、评审维度与总分
| 维度 | 满分 | 得分 | 说明 |
|------|------|------|------|
| 架构设计 (Architecture) | 25 | 21 | SO 事件总线 + ServiceLocator 整体优秀,但仍有混用 Instance/ServiceLocator |
| 性能 (Performance) | 25 | 20 | 批处理 / 对象池 / 环形缓冲区均到位3 处反射调用是负担 |
| 可扩展性 (Extensibility) | 20 | 17 | 谜题接口、EventChain、WorldStateRegistry 设计良好;对话变体未实装 |
| 编辑器友好 (Editor UX) | 15 | 13 | HurtBoxEditor / EventBusMonitorWindow 完善;极少数字段缺少 Tooltip |
| 使用便利性 (DX / API) | 15 | 12 | 核心 API 简洁namespace 缺失与 SaveManager.Instance 残留拉低得分 |
| **合计** | **100** | **83** | |
---
## 二、各维度详细评分与问题清单
### 2.1 架构设计 (21/25)
#### 优点
- **SO 事件频道体系**成熟,`BaseEventChannelSO<T>` + `EventSubscription(IDisposable)` + `CompositeDisposable.AddTo()` 完整闭环,各系统无直接依赖。
- **ServiceLocator** 统一服务注册,`GetOrDefault<T>` 优雅处理可选服务。
- **GameStateMachine** 显式白名单状态机避免非法转换DeepDive_2026 已完善。
- **25 个 asmdef** 严格单向依赖链Core → Player → Combat → … → World编译隔离优秀。
- **WorldStateRegistry** 作为 ScriptableObjectSO 注入代替全局单例,设计一流。
- **EventChainManager** 中继 C# 事件架构清晰Editor 专用静态事件零运行时开销。
#### 问题
| ID | 文件 | 描述 | 严重性 |
|----|------|------|--------|
| A-1 | `QuestManager.cs` | `OnEnable/OnDisable` 使用已废弃的 `SaveManager.Instance?.Register/Unregister` | 中 |
| A-2 | `ShopController.cs` | 同 A-1`SaveManager.Instance?.Register/Unregister` | 中 |
| A-3 | `EventChainManager.cs` | `Awake` 中使用 `SaveManager.Instance?.GetCompletedChains()` | 中 |
| A-4 | `TutorialManager.cs` | 使用原始 Singleton 模式(`public static Instance`),未注册 ServiceLocator | 低 |
| A-5 | `DialogueManager.cs` | `ResolveVariant()` 为存根,变体条件从未与 `WorldStateRegistry` 实际对接 | 低 |
---
### 2.2 性能 (20/25)
#### 优点
- `EventBusMonitor`:固定 256 条 `EventRecord[]` 环形缓冲区Editor 零 GC。
- `GlobalObjectPool``WarmupAsync` 预热,`IObjectPoolService` 接口注册,`ServiceLocator` 解耦。
- `BatchLOSSystem``HashSet + List` 双结构O(1) 查重 + 分帧限制 8 个请求。
- `EquipmentManager.UsedNotches`:缓存字段,完全消除 LINQ Sum。
- `AudioManager`6 路 SFX 轮转池避免高密度战斗音效互戳BGM 双 Source 交叉淡入淡出。
- `HomingProjectile`:方向向量用 `sqrMagnitude` 比较速度上限,无开方开销。
#### 问题
| ID | 文件 | 描述 | 严重性 |
|----|------|------|--------|
| P-1 | `LiquidZone.cs` | `PlayFeedback()` 通过 `GetMethod("PlayFeedbacks")` 反射调用,每次玩家进出液体区都触发 | 高 |
| P-2 | `PuzzleSwitch.cs` | 同 P-1同一反射模式 | 高 |
| P-3 | `PuzzleReceiver.cs` | 同 P-1同一反射模式 | 高 |
| P-4 | `Projectile.cs` | `ReturnToPool()` 使用 `GlobalObjectPool.Instance`(已标废弃),应走 ServiceLocator | 低 |
---
### 2.3 可扩展性 (17/20)
#### 优点
- `PuzzleInterfaces.cs``ISwitchable / IMovable / IActivatable` 三接口,谜题元素完全可替换实现。
- `AchievementCondition` + 11 个具体实现:抽象基类 + 工厂,新增成就类型零侵入现有代码。
- `EventChainSO` + `ChainCondition`ScriptableObject 配置驱动,策划可在 Inspector 搭建复杂叙事链。
- `WorldStateRegistry.WorldObjectCategory`:枚举泛化 API一个 registry 统一 Collectible/Door/Flag 等全部世界状态。
- `ToolSlotManager`:工具栏插槽与 SO 解耦,扩展新工具只需新建 ToolSO。
#### 问题
| ID | 文件 | 描述 | 严重性 |
|----|------|------|--------|
| E-1 | `DialogueManager.cs` | `ResolveVariant` 永远返回原始序列;条件分支对话完全无效 | 中 |
| E-2 | `AchievementManager.cs` | 注册为具体类型 `Register<AchievementManager>`,无法在测试中 mock | 低 |
---
### 2.4 编辑器友好 (13/15)
#### 优点
- `HurtBoxEditor`:运行时实时展示注入对象,调试受击逻辑极为便利。
- `EventBusMonitorWindow`:环形缓冲区在 Editor 窗口可视,零 GC。
- `BossSkillSequenceWindow`Boss 技能序列可视化 Inspector。
- `AddressKeyValidator`:构建时自动校验 Addressable Key 拼写,防止发布错误。
- `WorldStateRegistry.OnEnable() => _states.Clear()`:每次进入 Play Mode 自动重置 SO 状态,无脏数据问题。
- `EventChainManager``OnChainExecutedInEditor` 静态事件仅在编辑器存在,零运行时影响。
#### 问题
| ID | 文件 | 描述 | 严重性 |
|----|------|------|--------|
| UX-1 | 全局 | `SpeedrunTimer``AccessibilityManager` 缺少 namespaceIDE 浏览/搜索时易混淆 | 低 |
| UX-2 | `AntiSoftlockSystem.cs` | 类体未在 namespace 内缩进,与项目其他文件风格不一致 | 低 |
---
### 2.5 使用便利性API/DX(12/15)
#### 优点
- `ServiceLocator.GetOrDefault<T>(fallback)` 安全查询,代码调用方无需 null 判断。
- `DamageInfo.From(so, knockDir, sourcePos, layer)` 工厂方法 + `Builder`:两种构造路径清晰。
- `CompositeDisposable.AddTo()`Rx 风格订阅管理,防止事件泄漏。
- `QuestManager``IQuestManager` 接口 + `ServiceLocator.Register<IQuestManager>(this)`,调用方面向接口编程。
- `SkillSlotNames`:常量类消除 `"SoulSkill"` 等魔法字符串。
#### 问题
| ID | 文件 | 描述 | 严重性 |
|----|------|------|--------|
| D-1 | `SpeedrunTimer.cs` | 缺少 namespace与全局命名空间污染冲突 | 低 |
| D-2 | `AccessibilityManager.cs` | 缺少 namespace | 低 |
| D-3 | `UIManager.cs` | `TogglePause()` 只开不合,按两次暂停后第二次无效 | 中 |
| D-4 | `AchievementManager.cs` | `_saveRef` 字段在 `OnLoad` 赋值后从未读取(死代码) | 低 |
---
## 三、与商业标准的横向对比
| 对比项 | Hollow Knight 参照模式 | 本项目现状 |
|--------|------------------------|-----------|
| 事件解耦 | 自定义 C# 事件 + delegate | SO 频道体系,更 Inspector 友好 ✓ |
| 状态机 | 纯 C# 非 MonoBehaviour 状态 | 同PlayerStateBase 模式一致 ✓ |
| 对象池 | 静态池,键值 string | GlobalObjectPool + IObjectPoolService + ServiceLocator ✓✓ |
| 存档系统 | PlayerPrefs + 二进制 | Newtonsoft.Json + MD5 校验 + SemaphoreSlim 防并发 ✓✓ |
| 依赖注入 | 无(大量 singleton | ServiceLocator部分残留 singleton 待清理) ≈ |
| Addressables | Unity 自有 AssetBundle | Addressables + AddressKeyValidator 构建校验 ✓✓ |
| 谜题系统 | 基于碰撞的单一谜题 | ISwitchable/IActivatable 接口体系 ✓✓ |
| 对话变体 | 全局标记条件分支 | 框架存在但未接入 WorldStateRegistryTODO △ |
| 速通支持 | 无内置计时器 | SpeedrunTimer + ISaveable 持久化 ✓ |
| 无障碍 | 无内置色盲/震屏控制 | AccessibilityManager + ColorblindFilter ✓ |
---
## 四、修复项汇总(按优先级)
| 优先级 | ID | 文件 | 修复内容 |
|--------|----|------|----------|
| 高 | P-1,P-2,P-3 | `LiquidZone.cs`, `PuzzleSwitch.cs`, `PuzzleReceiver.cs` | 反射 → `MoreMountains.Feedbacks.MMFeedbacks` 直接转型 |
| 中 | A-1 | `QuestManager.cs` | `SaveManager.Instance``ServiceLocator.GetOrDefault<SaveManager>()` |
| 中 | A-2 | `ShopController.cs` | 同上 |
| 中 | A-3 | `EventChainManager.cs` | 同上 |
| 中 | D-3 | `UIManager.cs` | `TogglePause()` 改为真实 toggle |
| 低 | P-4 | `Projectile.cs` | `GlobalObjectPool.Instance``ServiceLocator.GetOrDefault<IObjectPoolService>()` |
| 低 | D-1 | `SpeedrunTimer.cs` | 补齐 namespace |
| 低 | D-2 | `AccessibilityManager.cs` | 补齐 namespace |
| 低 | D-4 | `AchievementManager.cs` | 删除 `_saveRef` 死代码字段 |
| 低 | UX-2 | `AntiSoftlockSystem.cs` | 类体补全缩进 |
---
## 五、不在本次修复范围内的已知问题(技术债)
| 问题 | 原因/说明 |
|------|----------|
| `DialogueManager.ResolveVariant()` 存根 | 需 Phase 4 完整接入 `WorldStateRegistry` 条件标记,属功能开发范畴,非代码质量问题 |
| `TutorialManager` raw singleton | 功能正确,仅可测试性不足;整改需新增接口,成本大于收益 |
| `AchievementManager` 注册具体类型 | 暂无 mock 需求,改为接口注册需新建 interface暂缓 |
| `AudioManager.PlayBGM/PlaySFX(key)` 存根 | 等待 Phase 2 AudioEventSO 模块,属功能开发范畴 |