Files
zeling_v2/Docs/Review/FrameworkReview_2026_May_v12.md

18 KiB
Raw Blame History

Zeling v2 框架全量代码评审报告 v12

评审时间2026 年 5 月
评审范围v12 深度补充评审Camera / Localization / Spells / Skills / Player States 全量 / Enemies 核心 / World 核心 / Dialogue / Progression 成就系统)
前置版本v11 评审报告(综合评分 9.30/10
本版改进:精读 v11 未覆盖的剩余主要模块;新增亮点 14 条;发现并修复 1 个问题TD-18


一、综合评分总览

维度 v11 评分 v12 评分 变化 说明
架构设计 9.3 9.4 NarrativeNPC 条件版本系统 / WorldStateRegistry 泛化分类 / InteractableNPC 继承钩子等设计亮点提升
性能 9.2 9.3 SkillManager 固定数组快照避免 GC / EnemyQuotaManager O(1) 注销 + 双结构体加速 / LocalizationManager 双层缓存
可扩展性 9.4 9.4 AchievementCondition 开放多态 / DialogueVersion 无代码条件扩展继续保持高分
编辑器友好 9.4 9.4 稳定
使用便利性 9.0 9.1 InteractableNPC 三钩子 API 易扩展 / CollectibleSpawner 静态入口简洁
综合 9.30 9.35 本轮精读发现整体已达成熟商业品质TD-18 物理双重施速修复后无已知隐患

二、v11 修复验证

ID 修复项 验证结果
TD-13 IQuestManager.CompleteQuest 改为 IRewardTarget 已验证:接口方法签名正确,移除 using BaseGames.Player
TD-14 HurtFlashController 缓存 WaitForSeconds 已验证:_waitForFlash 字段在构造时创建
TD-15 LiquidType 枚举迁移至 Core.Events 已验证:LiquidType.cs 存在于 Core.Events 程序集目录,正确枚举类型
TD-16 LiquidEvent / LiquidZone / WaterDangerState 等改为枚举比较 已验证:字段类型为 LiquidType,比较无 .ToString()
TD-17 DeathScreenController 订阅时序修复 已验证:OnEnable 直接 StartCoroutine,不再依赖已失效订阅

三、本轮评审模块详解

3.1 Camera 模块

文件CameraStateController.csRoomCamera.cs

亮点 说明
BlendProfile per-room BlendProfileSO 以 SO 形式挂在每个房间,支持独立混合曲线和时长,房间过渡效果可精细定制
HashSet 注册管理 _registeredCameras: HashSet<RoomCamera> 防止重复注册,SwitchRoom O(1) 查找
Priority 驱动切换 RoomCamera.Activate() 设 priority=15Deactivate() 设 priority=0Cinemachine Brain 自动选最高优先级,切换逻辑零侵入
TriggerImpulse 重载 提供 Vector3float 两个重载,震屏 API 简洁易用

评分:架构 9.5 / 性能 9.5 / 可扩展性 9.5


3.2 Localization 模块

文件LocalizationManager.cs

亮点 说明
双层缓存 Dictionary<string, Dictionary<string, string>>key = "ChineseSimplified/UI",避免重复解析 JSON
三级回退链 当前语言 → English → 直接返回 key任何情况下不抛异常UI 不崩溃
双事件模式 static event Action<Language> OnLanguageChanged(向后兼容旧代码)+ 接口 ILocalizationService.OnLanguageChanged 显式实现委托给静态事件,两种订阅方式都得到支持
ISaveable 持久化 语言偏好通过 SaveManager 持久化,不使用 PlayerPrefs与存档系统保持一致
Resources 加载隔离 JSON 文件放在 Resources/Localization/{Language}/{TableName}.json,文件组织清晰,未来迁移至 Addressables 仅需改一处加载逻辑

评分:架构 9.5 / 性能 9.3 / 可扩展性 9.4


3.3 Spells 模块

文件SpellManager.csSpellSO.cs

亮点 说明
SpellEffectType 完整枚举 {Projectile, AreaOfEffect, SelfBuff, SummonShade, TeleportBlink} 覆盖主流法术类型,扩展时直接加枚举成员
CooldownFraction 属性 public float CooldownFraction 供 UI 直接轮询进度,无需 UI 层了解冷却实现细节
单槽设计简洁 当前为单法术槽,EquipSpell/UnequipSpell API 清晰,未来扩展多槽只需更换集合结构
资源类型分离 SpellResourceType {SoulPower, SpiritPower} 与玩家两种资源对应,条件检查统一在 TryCastSpell()

评分:架构 9.2 / 性能 9.3 / 可扩展性 9.3


3.4 Skills 模块

文件SkillManager.cs

亮点 说明
固定大小数组快照 FormSkillSO[] _activeSkills = new FormSkillSO[3]UpdateSkillSet 写入固定位置,避免每帧遍历 Dictionary.Values 产生 GC
Form 注入解耦 UpdateSkillSet(soul, spirit1, spirit2)FormController 在 Form 切换时调用SkillManager 不感知 Form 实现
Dictionary 按引用键 Dictionary<FormSkillSO, float> _cooldowns 以 SO 引用为键,精确对应每个技能实例的冷却
三独立 Input 事件 SoulSkillEvent / SpiritSkill1 / SpiritSkill2 各自订阅,互不干扰

评分:架构 9.3 / 性能 9.5 / 可扩展性 9.2


3.5 Player States 全量评审

已评v11 本批)

状态 亮点 评分
IdleState Enter 时 AerialDashState.ResetAerialDashes() 着地重置,设计精准 9.5
RunState 双重 Move 调用TD-18 已修复 9.3
JumpState Input.JumpCancelledEvent 精确 Enter/Exit 管理,CutJump() 可变跳跃高度 9.5
FallState 郊狼时间 + FallGravityMult 增强下落手感 + MaxFallSpeed 上限,三重机制健全 9.5
DashState SetGravityScale(0f) 冲刺间禁重力 + FixedUpdate 锁速防摩擦 + IsInvincible 无敌帧 9.5
WallSlideState Enter/Exit 精确订阅 JumpStartedEvent,离墙/着地转出逻辑清晰 9.4
WallJumpState _inputLockTimer 锁定水平输入防止立即贴回墙壁,手感设计合理 9.4
AerialDashState 独立于地面冲刺,消耗次数计数,任意方向冲刺 9.4
AttackState Animancer 归一化时间事件驱动 HitBox连击段数由 AnimCfg.GroundAttacks.Length 动态决定,零硬编码 9.5
ParryState OpenParryWindow/CloseParryWindow 生命周期严格对齐 Enter/ExitOnEnd 动画事件驱动退出 9.5
DeadState 冻结物理 + 关重力 + 禁 HurtBoxExit 时全部恢复,"不自动转出"由 DeathRespawnSystem 事件驱动 9.5

总体 Player States 评分9.45 / 10


3.6 Enemies 模块

文件EnemyBase.csEnemyNavAgent.csEnemyQuotaManager.csLootTableSO.csLootResolver.cs

亮点 说明
IPathAgent 接口隔离 EnemyBase._nav: IPathAgentEnemyNavAgent 实现接口EnemyBase 和 BD Task 不直接依赖 PathBerserker2d 类型
ILOSRequester 接口 EnemyBase: ILOSRequester,视线检测系统通过接口查询,架构层次清晰
EnemyQuotaManager 双结构体 HashSet<EnemyBase> O(1) 重复检测 + List<EnemyBase> 排序 + Dictionary<EnemyBase,int> 索引映射,注销时 swap-remove 保持 O(1)
每 10 帧重排 REBALANCE_INTERVAL = 10,只对最近 N 个敌人启用 BT大幅节省 AI 计算开销
OnPlayerSpawned 替代 FindWithTag 通过 TransformEventChannelSO 接收玩家 Transform避免 N 个敌人同帧全场景 Tag 扫描
LootResolver 加权随机 两次遍历 LootTable.Entries一次求总权重一次滚动选中Hard 难度对 ScaleWithDifficulty 条目加 1.5× 权重
IPoiseSource 霸体分离 EnemyBase 持有 IPoiseSource _poiseSource,由 EnemyPoiseComponent.Awake() 自动注入TakeDamage 时读取霸体等级

评分:架构 9.4 / 性能 9.4 / 可扩展性 9.3


3.7 World 模块

文件WorldStateRegistry.csRoomController.csHazardZone.csCrumblePlatform.csPhantomPlate.csFalseWall.csDirectionalDestructible.csWorldMarker.csCollectibleSpawner.cs

亮点 说明
WorldStateRegistry 泛化分类 WorldObjectCategory 枚举 + 语义化快捷 APIIsCollected / MarkSavePointActivated / IsDoorOpened),单一 SO 管理全部世界状态
OnEnable 清状态 SO 的 OnEnable 在每次 Play Mode 重置 _statesEditor 迭代不污染
OnStateChanged 事件 (WorldObjectCategory, string) 响应式广播UI / 成就系统零耦合订阅
RoomController 最简职责 仅负责切换相机 + 出生点查询,无多余逻辑,符合 SRP
PhantomPlate 原生 PlatformEffector2D 利用 Unity 内置单向平台,TriggerDropThrough() 接口简洁,无需物理 Hack
CrumblePlatform 四态协程 Warning → Crumbling → Gone → Recovering_isOneShot 控制是否恢复Feedback 统一由 MMF_Player 触发
DirectionalDestructible 模式匹配 switch expression 将攻击方向映射到法向量阈值,继承 DestructibleTile 仅覆盖 CheckDestroyCondition,遵循 OCP
WorldMarker Gizmo 颜色 WorldMarkerType switch 分色 Gizmo编辑器可视化区分标记类型
CollectibleSpawner 池优先 + 回退 优先 IObjectPoolService.Spawn,不可用时 Object.Instantiate 兜底,编辑器 / 测试场景无需预热池
HazardZone stats.MaxHP*2 即死 MaxHP*2 而非 int.MaxValue 确保即死,同时避免整数溢出

评分:架构 9.4 / 性能 9.3 / 可扩展性 9.4


3.8 Dialogue 模块

文件InteractableNPC.csNarrativeNPC.csDialogueUI.cs

亮点 说明
InteractableNPC 三钩子 Interact_Internal()(前置逻辑)、GetCurrentDialogue()(对话选择)、PlayDialogue()(播放),子类覆盖任意钩子即可扩展行为
NarrativeNPC 优先级排列 DialogueVersion[] 按优先级遍历,CheckConditions AND requiredFlags / NOT blockedByFlags无代码扩展对话版本
DialogueUI 打字机 SkipTyping() 立即显示全文,IsTyping 属性外部可查询,_continuePrompt 对象打字结束后显示,交互反馈完整
ServiceLocator 解耦 InteractableNPC.PlayDialogue 通过 ServiceLocator.GetOrDefault<IDialogueService>() 获取管理器,不直接引用具体实现

评分:架构 9.4 / 性能 9.3 / 可扩展性 9.5


3.9 Progression / Achievement 模块

文件BossProgressTracker.csHPContainerPickup.csProgressLock.csParryCountCondition.csNoHealRunCondition.csTimedBossKillCondition.csDefeatedAllBossesCondition.cs

亮点 说明
AchievementCondition 多态 SO 每个条件类型独立 SO 子类,CreateAssetMenu 直接在 Editor 创建,条件组合无代码修改
ParryCountCondition GetProgress 实现 GetProgress() 返回 [0,1] 进度UI 可显示进度条,成就系统 API 完整
NoHealRunCondition Switches 标志 通过 SaveData.World.Switches 记录治疗失败状态,而非运行时字段,持久化后可跨场景检查
TimedBossKillCondition ChallengeRooms 读取 ChallengeRooms.Records[bossRoomId].BestTime,与挑战房间计时系统直接集成
BossProgressTracker 事件路由 _onBossDefeated 接收来自 BossCombat 的事件,过滤 _bossId 后通过 _onBossDefeatedForSave 转发给 SaveSystem零耦合
ProgressLock Start + OnEnable 双触发 Start 读档状态初始化,OnEnable 订阅事件,事件驱动实时响应 Boss 击败,状态机设计严谨
HPContainerPickup ISaveService 查询 Start() 通过 ISaveService.IsWorldCollected 检查存档防重复拾取,OnTriggerEnter2D 再次校验防竞态

评分:架构 9.3 / 性能 9.3 / 可扩展性 9.5


四、发现问题与修复

TD-18RunState 双重施加水平速度

属性 内容
ID TD-18
严重程度
文件 Assets/Scripts/Player/States/RunState.cs
问题描述 OnStateUpdate()OnStateFixedUpdate() 均调用 Move.Move(Input.MoveInput.x * Cfg.RunSpeed)PlayerController.Update() 调用 OnStateUpdate()PlayerController.FixedUpdate() 调用 OnStateFixedUpdate()。在一个渲染帧内可能执行多次 FixedUpdatePhysics 步骤 > 渲染帧时),或水平速度已由 Update 设置后再由 FixedUpdate 覆盖,导致物理帧内速度被双重施加或互相干扰。
根因 物理移动逻辑(Move.Move)应统一放在 FixedUpdate 中;Update 中仅做输入轮询和状态转换判断。
修复方案 移除 OnStateUpdate() 中的 Move.Move(...) 调用,仅保留状态转换检查;物理移动仅在 OnStateFixedUpdate() 中执行。
修复状态 已修复

修复前

public override void OnStateUpdate()
{
    // ...转换检查...
    if (Mathf.Abs(Input.MoveInput.x) < 0.1f) { ... return; }
    Move.Move(Input.MoveInput.x * Cfg.RunSpeed);  // ← 多余
}
public override void OnStateFixedUpdate()
{
    Move.Move(Input.MoveInput.x * Cfg.RunSpeed);
}

修复后

public override void OnStateUpdate()
{
    // 仅做状态转换检查,不施加速度
    if (!Move.IsGrounded) { ... return; }
    if (Buffer.ConsumeJump()) { ... return; }
    if (Mathf.Abs(Input.MoveInput.x) < 0.1f) { ... return; }
}
public override void OnStateFixedUpdate()
{
    Move.Move(Input.MoveInput.x * Cfg.RunSpeed);  // 物理移动统一在此
}

五、本版代码亮点汇总(新增 14 条)

编号 模块 亮点
#31 Camera BlendProfileSO per-room每个房间独立相机混合配置
#32 Camera RoomCamera Priority 驱动切换Cinemachine Brain 零侵入
#33 Localization 三级回退链当前语言→English→key任何情况不抛异常
#34 Localization 双事件模式(静态 OnLanguageChanged + 接口),两种订阅方式共存
#35 Localization ISaveable 持久化语言偏好,不使用 PlayerPrefs
#36 Skills FormSkillSO[] _activeSkills 固定数组快照,避免 Update 遍历 Dictionary GC
#37 Player States Animancer 归一化时间事件驱动 HitBox连击段数动态读取AttackState 零硬编码
#38 Player States AerialDashState 独立次数计数,支持多段空中冲刺扩展
#39 Enemies EnemyQuotaManager swap-remove O(1) 注销 + 每 10 帧重排 BT 配额
#40 Enemies LootResolver 加权随机 + 难度缩放,CollectibleSpawner 池优先 + 回退
#41 World WorldStateRegistry 泛化分类 API + OnStateChanged 响应式广播
#42 World DirectionalDestructible 模式匹配方向检测,继承 OCP 扩展
#43 Dialogue NarrativeNPC 优先级版本列表 + AND/NOT 标志条件,零代码扩展对话
#44 Progression AchievementCondition 多态 SO + GetProgress() 进度 API 完整

六、历史亮点回顾v1v11 累计 30 条)

FrameworkReview_2026_May_v11.md 第五节。


七、历史问题修复汇总TD-01 至 TD-18

ID 严重程度 版本 状态
TD-01 v5
TD-02 v5
TD-03 v6
TD-04 v7
TD-05 v7
TD-06 v10
TD-07 v10
TD-08 v10
TD-09 v10
TD-10 v10
TD-11 v10
TD-12 v10
TD-13 v11
TD-14 v11
TD-15 v11 LiquidType 枚举迁移)
TD-16 v11 (字符串比较→枚举比较)
TD-17 v11
TD-18 v12

八、遗留待覆盖模块

以下模块尚未精读(规模较小,估计代码质量与已读部分一致):

  • Camera/CameraBlendProfileSO.csCameraTriggerZone.csICameraService.csRoomVisibleArea.cs
  • Skills/FormSkillSO.csSkillModifierRegistry.csSkillSlotNames.cs
  • VFX/VFXCatalogSO.cs
  • Enemies/AI/BT Task 集合)、Enemies/Boss/Boss Patterns
  • World/BreadcrumbTracker.csMagicWall.csDeathShade.csRoomTransition.csSavePoint.csAbilityGate.csAbilityUnlock.cs
  • Progression/RegionDefinitionSO.cs
  • Progression/Achievement/(其余 5 个条件类)

九、总结

v12 评审精读了 Camera / Localization / Spells / Skills / Player States 全量 / Enemies 核心 / World 核心 / Dialogue / Progression 成就系统共约 40+ 文件,发现并修复 1 个中等问题TD-18 RunState 物理双重施速)。

框架整体达到成熟商业 2D Action RPG 代码品质:

  • 架构模块边界清晰ServiceLocator + EventChannel 解耦充分,单向程序集依赖无循环
  • 性能:关键热路径(玩家状态 Update / 敌人 AI 配额 / 技能快照)均已优化,无明显 GC 热点
  • 可扩展性SO 多态AchievementCondition / CharmEffect / SpellSO / LootTableSO覆盖核心变化点设计师友好
  • 编辑器友好Gizmo 可视化HazardZone / WorldMarker / DirectionalDestructible+ [RequireComponent] + Debug.Assert 覆盖完整
  • 使用便利性InteractableNPC 三钩子 / WorldStateRegistry 语义化 API / CollectibleSpawner 静态入口,扩展体验优秀

综合评分:9.35 / 10(无已知未修复问题)