Files
zeling_v2/Docs/Verification/10_Manual_ProgressionSystem.md
Joywayer 9aaa2b6452 docs: 修正进度系统文档中虚构的技能树系统
将 10_Manual_ProgressionSystem.md 中不存在的 SkillTreeSO/技能点/技能树解锁
流程,改写为真实实现:技能(FormSkillSO)随形态由 FormController 注入 SkillManager,
施放消耗魂力/灵力;能力通过 AbilityType 位掩码解锁(PlayerStats/AbilityFlags)。
同步更正 MT-PROG-06 的 HasAbility/存档字段引用,并统一 05/07/11 文档措辞为
'形态技能一览(FormSkillPanel)',明确本项目无技能树。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 11:39:57 +08:00

15 KiB
Raw Blame History

手动测试 10 · 进程与养成系统

测试类型Unity Editor 手动测试Play Mode
覆盖模块BaseGames.SkillsBaseGames.EquipmentBaseGames.QuestBaseGames.ProgressionBaseGames.World.Shop
依赖组件SkillManagerEquipmentManagerQuestManagerAchievementManagerShopKeeper
场景要求:含存档点、商店 NPC、任务触发器的完整测试场景


快速工具

工具 用途 菜单路径
Validate All ScriptableObjects 遍历所有实现 IValidatable 的 SO输出验证结果含 FormSkillSO、QuestDatabaseSO 等) BaseGames → Tools → Validate All ScriptableObjects

注意PlayModeDebugOverlay 已移除。Geo 注入、能力解锁测试等请通过 Inspector 直接修改对应 SO/Manager 字段,或临时编写 Editor 脚本触发。
Tab 10 的场景摆放工具Add Quest Trigger、Add Shop NPC已不再提供请参照下方各节手动步骤手工创建对应对象。

重要:本项目没有"技能点 + 技能树解锁"系统。 技能(FormSkillSO)随形态绑定,由 FormController 在切换形态时注入 SkillManager,无需花费技能点解锁;SkillTreePanel 仅为只读的形态技能一览面板。能力(二段跳/冲刺/形态等)通过 AbilityType 位掩码解锁(见 MT-PROG-06不涉及任何技能树。

典型工作流

  1. 测试前:BaseGames → Tools → Validate All ScriptableObjects 一键确认 SO 存在若有缺失Console 给出路径提示。
  2. MT-PROG-01 技能:进入 Play Mode通过 FormController 切换形态,确认 SkillManager 注入对应形态的三个技能,施放消耗魂力/灵力并进入冷却。
  3. MT-PROG-03 任务:手动放置 QuestGiver NPC见下方步骤QuestSO 拖入 InspectorPlay Mode 中交互验证。
  4. MT-PROG-05 商店:手动放置 ShopNPC(见下方步骤),通过 Inspector 修改 _geo 字段给玩家加钱,交互购买。

目录

  1. 前置数据检查
  2. MT-PROG-01形态技能与施放
  3. MT-PROG-02装备系统护符/武器)
  4. MT-PROG-03任务系统QuestManager
  5. MT-PROG-04成就系统AchievementManager
  6. MT-PROG-05商店系统Shop
  7. MT-PROG-06能力解锁AbilityUnlock

1. 前置数据检查

资产 路径(示例) 必要性
FormSkillSO ×N Assets/_Game/Data/Skills/SKL_*.asset 技能测试必须(每形态 3 个:魂技+灵技1+灵技2
EquipmentSlotConfigSO Assets/Data/Equipment/SlotConfig.asset 装备测试必须
QuestDatabaseSO Assets/Data/Quests/ 任务测试必须
AchievementDatabaseSO Assets/Data/Achievements/ 成就测试必须
ShopInventorySO Assets/Data/Shop/ 商店测试必须

🔧 一键检查 + 资产创建

步骤 1 — 验证资产存在性 菜单 BaseGames → Tools → Validate All ScriptableObjects

  • Console 输出每项 (通过)或 (失败/未找到)

步骤 2 — 创建所有占位 SO(若有缺失): 按照下方步骤 3 手动通过 Project 右键菜单创建对应资产。

步骤 3 — 创建尚未覆盖的数据资产(手动)

资产 创建方法
FormSkillSO Project 右键 → Create → BaseGames → Skills → Form Skill保存到 Assets/_Game/Data/Skills/,命名 SKL_{skillId};如有近战/爆炸判定再配套 SKL_{skillId}_HitBox 预制体
EquipmentSlotConfigSO Project 右键 → Create → BaseGames → Equipment → Slot Config保存到 Assets/_Game/Data/Equipment/
QuestDatabaseSO Project 右键 → Create → BaseGames → Quest → Quest Database保存到 Assets/_Game/Data/Quests/
AchievementDatabaseSO Project 右键 → Create → BaseGames → Progression → Achievement Database保存到 Assets/_Game/Data/Achievements/
ShopInventorySO 已由 Create Test Assets 创建为 ShopInventory_Test.asset;点 Inspector 的 + 按钮添加 ShopItem 条目

步骤 4 — 绑定 Manager 字段Play Mode 前):

  • 找到 Player 上的 SkillManager 组件 → Inspector → _formSkillSets 数组,按形态(天魂/地魂/命魂)逐项填入 soulSkill + spiritSkill1 + spiritSkill2(对应 FormSkillSO 资产)
  • 找到 ShopNPC GameObjectTab 10 → 添加商店 NPC_inventory 字段拖入 ShopInventory_Test.asset

MT-PROG-01形态技能与施放

目的:验证 SkillManager 的形态技能注入、技能施放、冷却管理、魂力/灵力消耗,以及 FormSkillPanel(只读技能一览)的展示。

架构说明(务必先读)

  • 技能 = FormSkillSO 资产,不通过技能点解锁。每个形态绑定 3 个技能槽:魂技(soulSkill+ 灵技1spiritSkill1+ 灵技2spiritSkill2)。
  • FormController 在切换形态时回调 SkillManager.UpdateSkillSet(...),把当前形态的三个技能注入到输入槽。玩家无须"学习"技能,切到该形态即可用。
  • 施放消耗的是魂力SoulPower或灵力SpiritPower(由 FormSkillSO.resourceType 决定),不是 MP。
  • FormSkillPanel(形态技能一览面板)只是只读一览:翻页查看各形态的技能图标/名称/描述/消耗/冷却,没有解锁交互、没有技能点、没有节点
  • 技能数值可被护符改写,见 MT-PROG-02 与 SkillModifierRegistry

🔧 资源准备

  1. 确认 Player 上 SkillManager._formSkillSets 已为待测形态填好三个 FormSkillSO
  2. 若待测形态尚未解锁(地魂/命魂),先解锁其形态能力:编辑 PlayerConfigSO.InitialAbilities 勾选 FormDiHun / FormMingHun,或临时写 Editor 脚本调用 PlayerStats.UnlockAbility(AbilityType.FormDiHun)。天魂(FormTianHun)默认初始解锁。
  3. 确认输入动作已绑定:魂技 = SoulSkillEvent灵技1 = SpiritSkill1StartedEvent灵技2 = SpiritSkill2StartedEvent(见 InputReaderSO)。

步骤

步骤 A形态切换注入技能

  1. 进入 Play Mode通过 FormController 切换到目标形态(切换输入键,或 Inspector 下调用 FormController.SwitchForm(FormType.XXX))。
  2. 观察 SkillManager 的当前技能(SoulSkill / Spirit1 / Spirit2 属性)。

预期

  • 切换形态后,SkillManager 的三个技能引用更新为该形态 _formSkillSets 中配置的技能。
  • 冷却字典 _cooldowns 重建并清零(切换后立即可施放)。
  • 若切换的是未解锁形态,FormController.SwitchFormHasAbility(FormXXX) 拦截,技能集不变。

步骤 B技能施放

  1. 进入战斗场景,按魂技/灵技1/灵技2 输入键。

预期

  • 技能动画播放(AnimancerComponent.Play(castAnimation))。
  • 资源扣减:SoulPower/SpiritPower -= effectiveCostPlayerStats.ConsumeSoulPower/ConsumeSpiritPower)。
  • 命中判定生成(若技能配了 SkillHitBoxPrefab,从对象池取实例并 Activate)。
  • 进入冷却(effectiveCooldown 秒内再次按键无效)。
  • 触发 skill_cast 反馈预设。

步骤 C资源不足时

  1. 使当前魂力/灵力 < effectiveCost(可在 Inspector 消耗资源或调小上限)。
  2. 按技能键。

预期ConsumeXxxPower 返回 false技能不释放无动画、无判定、不进冷却

步骤 D技能冷却

  1. 施放技能后立即再次按同一技能键。

预期:冷却期内 _cooldowns[skill] > 0不触发HUD 冷却指示(SoulCooldownRatio)显示剩余比例。

步骤 EFormSkillPanel 只读一览

  1. 打开技能一览面板(FormSkillPanel)。
  2. 左右翻页浏览各形态,确认当前实际形态被高亮(_activeFormIndicator)。

预期:面板展示各形态三技能的图标/名称/描述/消耗/冷却;无任何"解锁/锁定"状态或点击解锁交互(纯查看)。

检查点 期望
形态注入 切换形态后 SkillManager 三技能引用随之更新
未解锁形态拦截 切到未解锁形态被 HasAbility 拦截
技能施放 动画播放,判定生成,魂力/灵力扣减
资源不足 无法释放,不进冷却
冷却 冷却期无法再次使用,比例显示
一览面板 只读展示各形态技能,无解锁交互

MT-PROG-02装备系统护符/武器)

目的:验证 EquipmentManager 护符槽管理、装备属性叠加、超出槽数无法装备。

步骤

步骤 A装备护符

  1. 打开装备 UI默认 Tab 键或 E 键进入背包)
  2. 拖拽/确认护符到空槽位

预期

  • 护符装备成功,护符图标显示在槽位
  • 护符效果立即生效(如 HP+20查看 PlayerStats.MaxHP
  • EquipmentManager.IsEquipped(amuletId) == true

步骤 B槽位已满

  1. 将所有护符槽填满(maxAmuletSlots 个护符)
  2. 尝试装备第 maxAmuletSlots + 1 个护符

预期:系统提示"护符栏已满",无法装备(不会覆盖现有护符)。

步骤 C卸下护符

  1. 选中已装备的护符,点击"卸下"

预期

  • 护符移回背包
  • 护符提供的属性加成撤销HP 恢复原值)

步骤 D武器切换FormController 联动)

  1. 切换形态Sky/Earth/Death

预期:装备的武器 SO 根据形态切换,攻击力/攻击动画随形态变化。

检查点 期望
装备护符 效果立即生效,图标显示
槽位限制 超出槽数无法装备
卸下护符 属性加成撤销
形态武器 不同形态武器属性不同

MT-PROG-03任务系统QuestManager

目的:验证 QuestManager 的任务激活→进度追踪→完成→奖励全流程。

🔧 资源准备

  1. Tab 10 → 添加任务触发器QuestTrigger 一键放置 QuestTrigger GameObject含 CapsuleCollider2D
  2. 在 Inspector 中将 QuestTriggerSO手动创建Project 右键 → Create → BaseGames → Quest → QuestSO拖入 QuestTrigger._questToStart
  3. 确认 QuestDatabaseSO 中已注册该 QuestSO 条目

步骤

步骤 A任务激活

  1. 找到场景中的任务触发器(如 NPC 对话后触发任务)或手动调用 QuestManager.StartQuest(questId)
  2. 打开任务日志 UI

预期:任务出现在"进行中"列表,任务目标文本正确显示。

步骤 B进度追踪

  1. 完成部分任务目标(如击杀 X 敌人/收集 X 物品)
  2. 查看任务日志

预期:任务进度更新(如 "击杀 2/5 只敌人"EVT_QuestProgressUpdated 事件触发。

步骤 C任务完成

  1. 完成所有任务目标

预期

  • EVT_QuestCompleted 事件触发
  • 任务移入"已完成"列表
  • 奖励自动发放Geo/能力解锁/道具)
  • 存档文件中 SaveData.Quests[questId].IsCompleted == true
检查点 期望
任务激活 任务出现在进行中列表
进度追踪 完成目标后进度数字更新
完成奖励 奖励正确发放
持久化 存档中 IsCompleted == true

MT-PROG-04成就系统AchievementManager

目的:验证 AchievementManager 触发条件监听、达成弹窗、持久化。

步骤

  1. 触发某个成就的条件(如"首次击杀 Boss"、"连续弹反 5 次"等)

预期

  • 屏幕右上角弹出成就解锁通知(AchievementPopup
  • 通知显示成就名称和图标
  • EVT_AchievementUnlocked 触发
  1. 打开成就列表 UI

预期:该成就显示为已解锁状态(金色)。

  1. 退出并重新进入 Play Mode

预期:成就状态仍为已解锁(SaveData.Achievements 持久化)。

检查点 期望
触发弹窗 条件达成后弹出通知
列表状态 成就列表中显示已解锁
持久化 重进后仍为已解锁

MT-PROG-05商店系统Shop

目的:验证 ShopKeeper/ShopInventory 的购买/售出流程、Geo 扣减、背包更新。

🔧 资源准备

  1. 手动在场景中创建 ShopNPC GameObject添加 CapsuleCollider2D,并挂载 ShopNPC 组件
  2. 在 Inspector 中将 ShopInventory_Test.asset 拖入 ShopNPC._inventory
  3. 打开 ShopInventory_Test.asset,在 Inspector 展开 _items 数组,添加几个 ShopItem(配置 itemId、price、count
  4. Play Mode 中在 Inspector 直接将 PlayerController / GeoManager._geoCount 设为 500 快速获取购物用 Geo

步骤

步骤 A打开商店

  1. 走到商店 NPC按交互键

预期:商店 UI 打开,显示 ShopInventorySO 中的物品列表(价格、图标、名称)。

步骤 B购买物品

  1. 选择一个 Geo 充足的物品,确认购买

预期

  • CurrentGeo -= item.price
  • 物品出现在背包
  • HUD Geo 数量更新

步骤 CGeo 不足

  1. 选择价格超过当前 Geo 的物品

预期:购买失败,提示"Geo 不足"Geo 不变。

步骤 D售出物品

  1. 在商店卖出背包中的物品

预期

  • CurrentGeo += item.sellPrice
  • 物品从背包移除
  • HUD Geo 数量更新
检查点 期望
商店 UI 打开 物品列表正确显示
购买成功 Geo 减少,物品进背包
Geo 不足 购买失败Geo 不变
售出 Geo 增加,物品移除

MT-PROG-06能力解锁AbilityUnlock

目的验证特殊能力DoubleJump、WallCling、Dash 等 AbilityType 位)的解锁与 AbilityGate 联动。

步骤

  1. 确认某能力(如 DoubleJump当前未解锁
  2. 找到对应的能力解锁点Boss 击败后掉落,或特定区域触发)
  3. 触发解锁

预期

  • EVT_AbilityUnlocked(AbilityType) 触发(AbilityTypeEventChannelSOpayload 为解锁的能力位)
  • PlayerStats.HasAbility(ability) == true(位掩码 _unlockedAbilities |= ability
  • 存档中 SaveData.Player.AbilityFlags 含该能力位((uint)_unlockedAbilities
  • 对应 AbilityGate 自动开启(若当前场景有联动门)
  1. 测试新解锁的能力(如 DoubleJump跳跃后再次跳跃

预期:能力生效(二段跳可用)。

检查点 期望
解锁事件 EVT_AbilityUnlocked 触发
HasAbility == true PlayerStats.HasAbility 返回 true
AbilityGate 开启 对应能力门自动开启
能力可用 新能力实际可使用
持久化 存档 AbilityFlags 含该能力位