fix(ai): 应用 Task 1+2 代码审查意见

ResourceFull 未挂 BossResource 时改为显式抛——原先静默返回 false,
是 CLAUDE.md 第 6 条禁止的下游兜底,且与紧邻的 Boss facet 行为不一致。
FakeBossControl.DistanceToAnchor 不再忽略 index。测试改用 TearDown 清理
(本项目关闭了 Domain/Scene Reload,失败断言会把物体永久留在打开的场景里)。
BeginPhaseTransition 去掉死的默认参数;接口补充重入契约说明。

顺带去重:FakeAiContext 实现 IEnemyActor,删除两个测试内的本地 Ctx 副本
——一个接口成员改动要同步三份是复发性成本。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-30 12:31:39 +08:00
co-authored by Claude Opus 5
parent 3665504a58
commit 2a1ada4388
7 changed files with 60 additions and 77 deletions
@@ -38,8 +38,13 @@ namespace BaseGames.Enemies
/// <summary>当前 Boss 阶段索引。IBossControl 实现。</summary>
public int CurrentPhase => _currentPhase;
/// <summary>Boss 资源是否已满(未挂资源组件时恒为 false。IBossControl 实现。</summary>
public bool ResourceFull => _bossResource != null && _bossResource.IsFull;
/// <summary>Boss 资源是否已满。IBossControl 实现。
/// 未挂 BossResource 即抛——AI 图问了资源却没配资源组件是配置错误,必须暴露。</summary>
public bool ResourceFull => _bossResource != null
? _bossResource.IsFull
: throw new System.InvalidOperationException(
$"[BossBase] '{name}' 的 AI 图查询了资源满值,但未挂 BossResource 组件。" +
"请挂上该组件,或从 AI 图里移除资源相关的边。");
private Coroutine _counterStaggerCoroutine;
// 缓存加权候选与其有效权重(两者等长、下标对应),避免 UseBossSkillWeighted() 每次 new List → GC 分配
@@ -192,7 +197,7 @@ namespace BaseGames.Enemies
/// </summary>
/// <param name="targetPhase">过渡目标阶段索引。</param>
/// <param name="invincibleDuration">无敌帧持续时间(秒)。</param>
public void BeginPhaseTransition(int targetPhase, float invincibleDuration = 1.5f)
public void BeginPhaseTransition(int targetPhase, float invincibleDuration)
{
if (IsPhaseTransitioning)
{