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

8.9 KiB
Raw Blame History

代码深度评审 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-1SaveManager.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。
  • GlobalObjectPoolWarmupAsync 预热,IObjectPoolService 接口注册,ServiceLocator 解耦。
  • BatchLOSSystemHashSet + List 双结构O(1) 查重 + 分帧限制 8 个请求。
  • EquipmentManager.UsedNotches:缓存字段,完全消除 LINQ Sum。
  • AudioManager6 路 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.csISwitchable / IMovable / IActivatable 三接口,谜题元素完全可替换实现。
  • AchievementCondition + 11 个具体实现:抽象基类 + 工厂,新增成就类型零侵入现有代码。
  • EventChainSO + ChainConditionScriptableObject 配置驱动,策划可在 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。
  • BossSkillSequenceWindowBoss 技能序列可视化 Inspector。
  • AddressKeyValidator:构建时自动校验 Addressable Key 拼写,防止发布错误。
  • WorldStateRegistry.OnEnable() => _states.Clear():每次进入 Play Mode 自动重置 SO 状态,无脏数据问题。
  • EventChainManagerOnChainExecutedInEditor 静态事件仅在编辑器存在,零运行时影响。

问题

ID 文件 描述 严重性
UX-1 全局 SpeedrunTimerAccessibilityManager 缺少 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 风格订阅管理,防止事件泄漏。
  • QuestManagerIQuestManager 接口 + 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.InstanceServiceLocator.GetOrDefault<SaveManager>()
A-2 ShopController.cs 同上
A-3 EventChainManager.cs 同上
D-3 UIManager.cs TogglePause() 改为真实 toggle
P-4 Projectile.cs GlobalObjectPool.InstanceServiceLocator.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 模块,属功能开发范畴