18 KiB
Architecture vs Design 全面审查报告
审查日期:2025-01
审查范围:Docs/Architecture/(24 份文档)← →Docs/Design/(74 份文档)
审查方法:人工逐节比对核心模块,重点覆盖战斗、弹反、霸体、护盾、玩家、墙壁力学
结论:00_CoverageIndex.md声称"架构完整度 100%"与实际不符,存在若干严重错误、内部矛盾和实现细节缺失
一、总体评估
| 维度 | 声称状态 | 实际状态 |
|---|---|---|
| 内容覆盖(所有 Design 文档均有对应章节) | ✅ 100% | ✅ 基本完整,极少遗漏 |
| 技术数值/枚举值准确性 | ✅ 完整 | 🔴 多处严重错误 |
| 架构文档内部一致性 | ✅ 完整 | 🔴 存在互相矛盾的代码片段 |
| 与 Design 意图对齐(设计意图传达) | ✅ 完整 | 🟠 3 个系统根本设计不同 |
| 实现细节充分度 | ✅ 完整 | 🟡 部分模块细节不足 |
二、🔴 严重错误(Critical)—— 必须修正,按此实现将产生 Bug
D-01 · PoiseSystem 根本设计不同
位置:06_CombatModule.md §13 vs Design/54_PoiseSystem.md
Architecture 描述的是数值耐久条系统,Design 定义的是等级比较系统——两者是完全不同的机制。
| 对比项 | Architecture 06 §13 | Design 54(正确版本) |
|---|---|---|
| 系统类型 | 数值耐久(int _currentPoise -= X) |
等级比较((int)breakLevel >= (int)poiseLevel) |
| 适用对象 | 仅敌人(注释"玩家不使用霸体系统") | 玩家和敌人均有霸体 |
| 玩家霸体 | 不存在 | IPoiseSource 接口,PlayerController 实现,攻击/技能期间激活 |
| 枚举结构 | 单一 BreakLevel 枚举 |
两个独立枚举:PoiseLevel(承受方)和 BreakLevel(攻击方) |
| 时间窗口 | 无 | PoiseWindowConfig struct,可为每个状态/技能配置时间窗口 |
| 精细规则 | GetPoiseBreakAmount(info) 隐式处理 |
PoiseOverrideTableSO — 显式配置 sourceId 对特定目标的精细规则 |
Architecture BreakLevel 枚举值错误(影响伤害管线中所有使用 BreakLevel 的比较逻辑):
// Architecture 06 §2(错误)
public enum BreakLevel
{
Light = 0, // 值错误
Heavy = 1, // 值错误
Super = 2, // 名称错误(Design 中无此值)
Unbreakable = 99, // 值错误
}
// Design 54(正确)
public enum BreakLevel { None=0, Light=1, Medium=2, Heavy=3, Breaker=4 }
public enum PoiseLevel { None=0, Light=1, Medium=2, Heavy=3, Unbreakable=100 }
缺少的关键组件:
IPoiseSource接口(PlayerController实现,提供CurrentPoiseLevel和GetPoiseWindow())PoiseWindowConfig结构体(每个动画状态/技能的霸体等级 + 起止时间窗口)PoiseOverrideTableSO(游戏资产,细粒度控制特定来源 vs 特定目标的打断规则)DamageSourceSO中的BreakLevel字段应对应正确的枚举值范围
D-02 · ParryConfigSO 数值与字段全部错误
位置:06_CombatModule.md §9 vs Design/05_ParrySystem.md §9
// Architecture 06 §9(错误)
public class ParryConfigSO : ScriptableObject
{
public float ParryWindowDuration = 0.4f; // ❌ 应为 WindowDuration = 0.28s
public float PerfectParryWindow = 0.1f; // ❌ 字段名不符,且设计无此独立字段
public float ParryCooldown = 0.3f; // ⚠️ 设计未定义此字段
public int SoulPowerOnParry = 20; // ❌ 应为 SoulGainOnParry = 33
public int SoulPowerOnPerfect = 40; // ❌ 应为 +50(Perfect 额外奖励)
public float PerfectParryCounterDmg = 1.5f; // ❌ 应为 ParryCounterMultiplier = 3.0
// ❌ 缺少以下字段:
// StartupDuration = 0.05f 弹反启动前摇
// EndlagDuration = 0.10f 弹反后摇
// CounterWindowDuration = 0.5f 弹反成功后的反击窗口
// BulletTimeScale = 0.25f 成功弹反时的子弹时间倍率
// BulletTimeDuration = 0.2f 子弹时间持续
// StaggerDuration = 0.8f 被弹反敌人的硬直时长
}
| 字段 | Architecture | Design(正确值) |
|---|---|---|
| 弹反窗口 | 0.4f | 0.28s |
| 普通弹反灵力 | 20 | 33 |
| 完美弹反灵力 | 40 | +50(累计 83) |
| 完美弹反伤害倍率 | 1.5× | 3.0× |
| 启动前摇 | 缺失 | 0.05s |
| 后摇 | 缺失 | 0.10s |
| 反击窗口 | 缺失 | 0.5s |
| 子弹时间倍率 | 缺失 | 0.25 |
D-03 · HurtBox.ReceiveDamage() 存在两个互相矛盾的版本
位置:06_CombatModule.md §5 vs 20_ShieldModule.md §2
两个文档对同一方法有不同定义,行为互相不兼容:
版本 A(06_CombatModule §5):
// 护盾处理后,若 Amount > 0,HurtBox 继续调用 _owner.TakeDamage
if (_shieldable != null && _shieldable.HasShield)
{
_shieldable.AbsorbDamage(ref info);
if (info.Amount <= 0) return; // 完全吸收才退出
}
int finalDamage = Mathf.Max(1, info.Amount - _owner.Defense);
_owner.TakeDamage(info); // 穿透伤害由 HurtBox 直接调用 TakeDamage
版本 B(20_ShieldModule §2,标注为"修改 06_CombatModule §2 的实现"):
// 护盾处理后总是 return,穿透伤害通过事件传递
if (_shieldable != null && _shieldable.HasShield)
{
_shieldable.AbsorbDamage(ref info);
return; // 总是退出!穿透由 ShieldComponent 内部触发 _onDamagePassedThrough 事件
}
_damageable?.TakeDamage(info); // 无护盾时才直接调用
冲突后果:若使用版本 A,当护盾未完全吸收时,HurtBox 直接调用 TakeDamage,同时 ShieldComponent.AbsorbDamage 也触发 _onDamagePassedThrough 事件通知 PlayerStats——玩家受到双倍穿透伤害。
版本 B(ShieldModule 提供)才是正确的"护盾总线"设计,版本 A 需要移除护盾后的穿透处理逻辑。
附加差异:版本 A 有无敌帧检查,版本 B 没有;版本 B 有 if (!_isActive) return; 保护,版本 A 没有。
三、🟠 重要问题(High)—— 实现时需要大量补充或会导致功能不完整
D-04 · ParrySystem 缺少完整状态机
位置:06_CombatModule.md §8 vs Design/05_ParrySystem.md
Architecture 的 ParrySystem 仅有一个 bool _isParrying + 单计时器,Design 定义了5 阶段状态机:
Design 05 正确状态机:
Inactive → Startup(0.05s) → Active(0.28s) → ParrySuccess → CounterWindow(0.5s) → Inactive
Architecture 06 实现:
_isParrying = true/false + _parryWindowTimer(单一计时器,无阶段区分)
缺少的阶段及行为:
- Startup(前摇):0.05s,期间无法弹反但玩家进入弹反动画,给予视觉反馈
- EndLag(后摇):弹反结束后 0.1s,防止立即连续弹反
- CounterWindow(反击窗口):弹反成功后 0.5s,玩家可使用强化攻击(×3 倍率)
_isParrying > _config.PerfectParryWindow的"完美弹反"判定逻辑依赖 Startup 计时,但 Architecture 未建模
D-05 · HandleSuccessfulParry() 方法不存在
位置:20_ShieldModule.md §8 引用 vs 06_CombatModule.md §8
20_ShieldModule.md §8 弹反集成 第 311 行写道:
ParrySystem.HandleSuccessfulParry()末尾调用:shield.OnParrySuccess();
但 06_CombatModule.md §8 ParrySystem 中,该类只有:
TryActivateParry()TryParryDamage(DamageInfo info)ApplyPerfectParryEffect(DamageInfo info)EndParry(bool success)
HandleSuccessfulParry() 方法在架构中未定义,两个文档引用的不是同一个 API。
同时,ShieldComponent.OnParrySuccess() 的调用路径也有两个版本:
20_ShieldModule §6 表格:"弹反成功 |ParrySystem.OnParrySuccess(SO 事件)→ShieldComponent.OnParrySuccess()"20_ShieldModule §8 代码:ParrySystem.HandleSuccessfulParry()内直接TryGetComponent<ShieldComponent>()调用
两种集成方式并存,需要统一。
D-06 · OnParrySuccess 事件频道类型错误
位置:06_CombatModule.md §8 vs Design/05_ParrySystem.md §10
// Architecture 06 §8(错误)
[SerializeField] private VoidEventChannelSO _onParrySuccess;
// 仅广播"发生了弹反",无附加数据
// Design 05 §10(正确)
// OnParrySuccess 应为 DamageInfoEventChannelSO
// 携带 DamageInfo payload,下游系统根据 info 计算反击伤害量、特效强度等
VoidEventChannelSO 不携带 DamageInfo,导致:
CounterWindow期间的反击伤害无法基于原始攻击力计算(×3 倍率)ParryableProjectile.HandleParry(ParryInfo parry)签名中的ParryInfo结构在其他地方未定义
D-07 · HurtBox 流程图声称有霸体检查但代码没有实现
位置:06_CombatModule.md §6 伤害流水线(流程图)vs §5 HurtBox 代码
§6 流程图文字:
→ HurtBox.ReceiveDamage(info)
→ 检查无敌帧(IgnoreIFrame flag)
→ 检查霸体(BreakLevel vs Poise) ← 流程图列出此步骤
→ 计算 FinalDamage = RawDamage - Defense(最低 1)
但 §5 的 HurtBox.ReceiveDamage() 代码完全没有霸体检查逻辑,直接从无敌帧检查跳到护盾检查。
按 Design 54,霸体检查(PoiseLevel vs BreakLevel)应该在 HurtBox 中完成,而不是在 EnemyBase.TakeDamage() 内部。
四、🟡 中等问题(Medium)—— 存在缺失或不清晰,实现时需补充
D-08 · 墙壁力学实现细节严重不足
位置:05_PlayerModule.md §3 + §12 FSM 表格 vs Design/26_WallMechanicsSystem.md
Architecture 在 FSM 表格中列出了 WallSlideState、WallJumpState,但没有任何详细实现描述。
| 功能 | Architecture | Design 26(要求实现) |
|---|---|---|
| 墙面检测 | §3:每侧单射线(CheckWalls()) |
双射线(TopRay + BottomRay),防止卡角 |
| 墙壁抓取 | 未提及 | WallGrab 机制——碰墙后自动抓取,不需要持续按键 |
| 高度记录 | 未提及 | wallGrabY 记录抓取时 Y 坐标,防止无限蹬墙高度增益 |
| 跳墙类型 | 未说明 | 两种:背墙跳(同方向弹出)和对墙跳(反方向飞离),有不同速度向量 |
| 专用组件 | 无 | PlayerWallDetector 组件(独立,保持 PlayerMovement 干净) |
| 配置 SO | §15 中有 WallSlideSpeed、WallJumpForce 等 |
应独立为 WallMechanicsConfigSO |
WallSlideState 和 WallJumpState 的 OnStateEnter、OnStateUpdate、OnStateExit 实现完全缺失。
D-09 · ParryableProjectile 订阅机制未说明清楚
位置:06_CombatModule.md §7
代码中出现两种订阅机制:
ParrySystem.OnParrySuccess += HandleParry(C# 静态事件或实例委托)ParrySystem类中_onParrySuccess是VoidEventChannelSO(ScriptableObject 事件频道)
架构文档没有说明 ParrySystem.OnParrySuccess 是一个 C# 事件而非 SO 频道,且与 _onParrySuccess 字段的关系未交代。HandleParry(ParryInfo parry) 的 ParryInfo 结构体在整个架构文档中均未定义。
D-10 · DamageInfo 与 Design 定义不完全对齐
位置:06_CombatModule.md §1 vs Design/04_CombatSystem.md §2
| 对比项 | Architecture | Design |
|---|---|---|
| 结构特性 | struct,有可变 Amount 字段 |
"只读值类型,不可修改" |
| 中间值字段 | 添加了 Amount(流水线中间量) |
无 Amount,只有 RawDamage / FinalDamage |
SkillId 字段 |
有 | 无(Design 版本较简洁) |
Architecture 的版本更详细(Builder 模式、Amount 流水线字段、SkillId),技术上是对 Design 的合理扩展,但与 Design 声称的"不可修改"矛盾。需要明确说明这是架构层面的有意设计决策。
五、🔵 轻微问题(Minor)—— 不影响实现正确性,但影响文档准确性
D-11 · 覆盖率索引节号标注错误
位置:00_CoverageIndex.md 中关于 16_SupportingModules 的引用
| 覆盖索引声称 | 实际节号(16_SupportingModules.md) |
|---|---|
| §7 = AnalyticsManager | 错误 — §7 是"支撑事件频道清单" |
| §8 = SpeedrunTimer | 错误 — §8 是 AnalyticsManager |
| — | §9 = SpeedrunTimer(索引中未提及) |
D-12 · ShieldComponent.AbsorbDamage 签名与 Design 不同
位置:20_ShieldModule.md §5 IShieldable vs Design/30_ShieldMechanicsSystem.md
- Architecture:
void AbsorbDamage(ref DamageInfo info)(通过 ref 修改 Amount,穿透走事件总线) - Design:返回
int(穿透量),由调用方处理
Architecture 版本是更符合 C# 规范的架构设计,但应在文档中注明这是对 Design 的有意修改,而非与 Design 保持一致。
六、✅ 经人工核实正确的内容
以下内容经过手动比对,与对应 Design 文档基本一致:
| 架构文档 | 核实内容 |
|---|---|
07_EnemyModule.md §14 |
LootSystem:LootTableSO、LootResolver、LootPickup 均完整定义 |
09_ProgressionModule.md §2 |
AbilityGate 系统存在且逻辑完整 |
09_ProgressionModule.md §7.5 |
ToolSlotManager、ToolHUD 存在 |
14_NarrativeModule.md §5-7 |
EventChainSO、EventChainManager、CutsceneSO、CutsceneTrigger 均完整 |
16_SupportingModules.md §4 |
DebugCheatSystem、DebugCheatOverlay 均存在 |
16_SupportingModules.md §8-9 |
AnalyticsManager、SpeedrunTimer 均存在 |
20_ShieldModule.md §1-9 |
整体架构完整(IShieldable、ShieldComponent、ShieldConfigSO、SaveData 集成) |
21_LiquidPuzzleModule.md |
LiquidZone/SwimState、PuzzleSwitch/PuzzleReceiver/PuzzleWire、TutorialManager 均完整 |
06_CombatModule.md §3 |
DamageSourceSO 结构完整,含 sourceId、skillId、ComboWindowDuration |
06_CombatModule.md §4 |
HitBox 寄宿规则(武器/技能 Prefab 子节点)设计合理,与 Design 一致 |
06_CombatModule.md §14 |
IBreakable/BreakConditionSO 机关交互系统设计完整 |
七、未能全面核实的文档
以下架构文档在本次审查中未进行深度手动比对,结论依赖 00_CoverageIndex.md 的自评:
| 架构文档 | 对应 Design 文档 | 风险评估 |
|---|---|---|
08_WorldModule.md |
Design 08, 10, 17, 27, 29, 32, 34, 37, 42-44, 46, 48, 50, 52(多达 14 份) | ⚠️ 范围最广,建议优先补充核实 |
10_UIModule.md |
Design 11, 21-25, 33, 53, 57, 70 | ⚠️ UI 相关 Design 较多,节号/字段有错误风险 |
11_AudioModule.md |
Design 12_AudioSystem | 🟢 FMOD 集成逻辑相对独立,风险较低 |
12_SaveModule.md |
Design 31_SaveDataSchema_Unified | ⚠️ SaveMigrator 细节值得核实 |
17_CameraModule.md |
Design 02_CameraSystem | 🟢 Cinemachine 配置,风险较低 |
18_VFXFeedbackModule.md |
Design 07_FeedbackSystem, 41_VFXArchitecture | ⚠️ Feel/MoreMountains 集成,参数可能有出入 |
22_QuestChallengeModule.md |
Design 38_QuestSystem, 39_ChallengeRoomSystem | ⚠️ 建议核实 |
23_BossSkillModule.md |
Design 19_BossPatternLibrary, 47_BossSkillSystem | ⚠️ Boss 技能系统复杂,建议核实 |
24_AnimEventModule.md |
Design 20_AnimationEventSystem | 🟢 事件名称列表性质,风险较低 |
八、修正优先级与行动计划
P0(立即修正,影响一切基于此的实现)
- 修正
06_CombatModule.md §2 BreakLevel枚举:按 Design 54 改为{None=0, Light=1, Medium=2, Heavy=3, Breaker=4},并新增独立的PoiseLevel {None=0, Light=1, Medium=2, Heavy=3, Unbreakable=100}枚举 - 重写
06_CombatModule.md §13 PoiseSystem:按 Design 54 改为等级比较系统,覆盖玩家和敌人,新增IPoiseSource、PoiseWindowConfig、PoiseOverrideTableSO - 统一
HurtBox.ReceiveDamage()版本:确定以20_ShieldModule §2版本为准(护盾命中总 return,穿透走事件),删除06_CombatModule §5中护盾后的直接 TakeDamage 路径
P1(高优先级修正,影响弹反/战斗核心功能)
- 修正
06_CombatModule.md §9 ParryConfigSO:更新所有数值(窗口 0.28s,灵力 33/+50,反击倍率 3.0),添加 Startup/EndLag/CounterWindow/BulletTime 字段 - 扩展
06_CombatModule.md §8 ParrySystem:添加 5 阶段状态机(Startup→Active→ParrySuccess→CounterWindow→Inactive),定义HandleSuccessfulParry()方法或统一为TryParryDamage()路径 - 修正
_onParrySuccess事件类型:从VoidEventChannelSO改为DamageInfoEventChannelSO - 修正
20_ShieldModule.md §8:将HandleSuccessfulParry()改为架构中实际存在的方法名
P2(中优先级,实现时需补充)
- 补充
05_PlayerModule.md墙壁力学实现细节:添加WallSlideState/WallJumpState的详细实现,双射线检测,WallGrab机制,wallGrabY高度记录,两种跳墙方式,PlayerWallDetector组件 - 在
06_CombatModule.md §5 HurtBox代码中补充霸体检查逻辑(使其与 §6 流程图一致) - 定义
ParryInfo结构体(供ParryableProjectile.HandleParry使用)
P3(轻微,不影响实现)
- 修正
00_CoverageIndex.md节号:§7为事件频道清单,§8为 AnalyticsManager,§9为 SpeedrunTimer - 在架构文档中注明
DamageInfo.Amount字段和AbsorbDamage(ref DamageInfo)签名是对 Design 的有意架构决策(而非错误)
九、审查结论
Docs/Architecture/ 在覆盖广度上基本达到 Design 文档的全部技术范围,但**"架构完整度 100%"的自评不符合实际**:
- 战斗核心三角(HurtBox 伤害流水线 × 弹反系统 × 霸体系统)存在多处相互矛盾或错误的定义
- PoiseSystem 是最严重的设计偏差——Architecture 和 Design 是两套根本不同的机制,直接影响玩家霸体、攻击打断、Boss 超甲等核心手感
- ParryConfigSO 的所有数值均错误,弹反手感将完全不符合设计意图
- HurtBox 双版本矛盾是最危险的隐患——如不统一,护盾命中将产生双倍伤害 Bug
建议在正式开始实现战斗模块之前,完成 P0 和 P1 级别的修正。