4.3 KiB
阶段4C2收线取消缺陷最小修复方案(待完整评审)
2026-09-24。依据:《阶段4C2第二次真实尝试与收线取消记录-2026-09-24.md》及用户提供的完整错误堆栈。仅修复已实证缺陷,不放宽任何准入/技能检查/票据保护;未编码。
缺陷与证据
用户真实收线完成时(FishEnd 已触发)报错堆栈:
PlayerKVGameplayLoop:Fault ← CancelReward ← FishingUpdateSys:OnDisable(FishingUpdateSys.cs:3203)
← UnityEngine.Object:Destroy ← UIManager:DestroyUI(UIManager.cs:938)
← FishingUpdateSys:FishEndCore(:1312) ← FishEnd(:1255) ← Update(:1227)
正常完成链为 FishEnd → BeginRewardEnding(置a.Ending=true) → using BeginRewardSegment("ending") FishEndCore() → ShowKVRewardPanelAsync(等待票据确认后展示)。FishEndCore 内 UIManager.Instance.DestroyUI(UITypes.FishingPanel)(:1311)会销毁承载 FishingUpdateSys 的战斗面板,同步触发 OnDisable/OnDestroy → CancelReward(this,...)。CancelReward(UserService.KVFishingReward.cs:281-288)只校验 actor 身份,不区分该拆除是否属于完成路径自身:a.Cancelled=true 且此刻 Ready && !a.Confirmed → Fault("Fishing reward cancelled: controller disabled"),奖励在确认前被自己的收尾拆除取消。第二次真实尝试(run 62216)即此:门通过、扣费票据确认、战斗约18秒正常结束,随后被误取消退出,无奖励。
拟改动1(生产,唯一行为变化):UserService.KVFishingReward.cs CancelReward 增加一行守卫
在现有 actor 身份守卫之后、a.Cancelled=true 之前增加:
if(a.Ending && !a.Confirmed && ReferenceEquals(actor,a.Controller)) return;
语义:已进入完成流程(Ending=true)且尚未票据确认(!Confirmed)时,控制器(Controller)自身的 disable/destroy 属于 FishEndCore 的正常拆除窗口,不构成放弃。
- 战斗中(Ending=false)控制器被禁用/销毁:仍按原逻辑取消并 Fault(真实放弃保护保留)。
- 票据确认之后控制器 disable:守卫不适用(Confirmed=true),保持原语义——置 Cancelled、不 Fault(既有固定验证用例"confirmed-normal-cancel-no-second-exit"期望不变)。
- Panel 与 Consumption.Actor 两个 actor 路径完全不变;合法放弃主通道
CancelFishing→CancelReward(action.Actor)(KVGameplayLoop.cs:195)不受影响。 - 若该窗口内票据确认本身失败,仍由 ConfirmRewardAsync 的既有 Stop/Fault 报错,不产生悬空奖励。
不新增字段、事件、日志框架、await;不动 CheckRewardContext、技能检查、准入、票据等待、Fault 通道。
拟改动2(既有固定验证维护):UserService.KVFishingRewardValidation.cs 增加一组用例
新增组(命名如 ending-teardown-pre-confirm-not-cancel):构造 rewardAction → BeginRewardEnding 成功后、ConfirmRewardAsync 完成前,模拟控制器 disable(调用 CancelReward(rewardAction.Controller,"controller disabled"))→ 断言 !rewardAction.Cancelled && Ready(红:现状会 Cancelled+Fault);随后正常完成确认与展示,断言流程可走完。既有"confirmed-normal-cancel-no-second-exit"用例保持原样(验证确认后语义未变)。
验收
- 固定验证全量重跑:既有43组168断言+新增组全部通过(Unity空闲Editor执行
KVGameplayLoopSetup.RunValidationAsync("fishing-reward"))。 - Editor编译0错误、SERVICE_HOST编译exit0。
- 静态diff判据:生产源码仅 UserService.KVFishingReward.cs 一行守卫+Validation文件新增用例段;FishingUpdateSys.cs、FishingRewardPanel.cs、KVGameplayLoop.cs 等其余文件字节不变。
- 修复后真实收鱼闭环仍需用户另行授权新进程运行;本修复不构成4C2关闭。
请独立评审裁决
- 守卫条件
Ending && !Confirmed && actor==Controller是否精确覆盖且仅覆盖误取消窗口?有无遗漏的取消场景(如FishEnd开始后用户真实退出应如何表现——应经CancelFishing/退出排水路径)? - 确认后语义不变的论证是否成立(对照既有验证用例)?
- 新增验证用例设计是否充分(红绿边界)?
- 是否批准这两处限定修改?
请输出问题等级(P1/P2/P3)、可执行修订与明确允许/不允许实施结论。