fix(enemy): Approach 逼近改用 aggro/视野双刷新的 LastKnown(修 aggro 先命中扑向错误点)+补 Attack 退出测试
This commit is contained in:
@@ -357,6 +357,33 @@ namespace BaseGames.Tests.EditMode.AI
|
||||
Assert.AreEqual("Death", rt.CurrentStateName);
|
||||
}
|
||||
|
||||
// 进 Attack 后玩家脱离全部感知区:攻击仍在跑 → 不回 Approach,改判 leftAllZones → Rest(Patrol)。
|
||||
[Test]
|
||||
public void Attack_ToRest_WhenLeftAllZones()
|
||||
{
|
||||
var ctx = new Ctx();
|
||||
var rt = new AiRuntime(GraphApproach(), ctx);
|
||||
ctx.S.Chase = true; rt.Tick(0.1f); // → Approach
|
||||
ctx.C.Eligible = true; rt.Tick(0.1f); // → Attack, Running="best"
|
||||
Assert.AreEqual("Attack", rt.CurrentStateName);
|
||||
ctx.S.Chase = false; ctx.S.Vision = false; // 攻击仍 running,但脱离全部感知
|
||||
rt.Tick(0.1f);
|
||||
Assert.AreEqual("Patrol", rt.CurrentStateName);
|
||||
}
|
||||
|
||||
// 死亡是全局事件,从 Attack 态也能达 Death。
|
||||
[Test]
|
||||
public void ApproachAttack_Death_FromAttack()
|
||||
{
|
||||
var ctx = new Ctx();
|
||||
var rt = new AiRuntime(GraphApproach(), ctx);
|
||||
ctx.S.Chase = true; rt.Tick(0.1f); // → Approach
|
||||
ctx.C.Eligible = true; rt.Tick(0.1f); // → Attack
|
||||
Assert.AreEqual("Attack", rt.CurrentStateName);
|
||||
rt.Send(AiSignal.Died); rt.Tick(0.1f);
|
||||
Assert.AreEqual("Death", rt.CurrentStateName);
|
||||
}
|
||||
|
||||
// ── 死亡(全局事件,任意态可达)───────────────────────────────────
|
||||
|
||||
[Test]
|
||||
|
||||
@@ -26,15 +26,14 @@ namespace BaseGames.Enemies
|
||||
/// <summary>每帧由 EnemyAiBrain 在 Tick 之前调用,维护最后已知位置与丢失计时(供需要的敌人用)。</summary>
|
||||
public void Refresh(float dt)
|
||||
{
|
||||
if (InVisionZone() && _enemy.PlayerTransform != null)
|
||||
{
|
||||
bool vision = InVisionZone();
|
||||
// 追逐区(aggro)或视野内都刷新最后已知位置:Approach 逼近态仅由 aggro 门控进入,
|
||||
// 若只在视野时刷新,aggro 先于视野命中时 Pursue 会拿到 zero/过期点而扑向错误位置。
|
||||
if ((vision || InChaseZone()) && _enemy.PlayerTransform != null)
|
||||
_lastKnown = _enemy.PlayerTransform.position;
|
||||
_lostTimer = 0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
_lostTimer += dt;
|
||||
}
|
||||
// 丢失计时仍以视野为准(LostFor 语义=脱离视野的时长,不受 aggro 影响)。
|
||||
if (vision) _lostTimer = 0f;
|
||||
else _lostTimer += dt;
|
||||
}
|
||||
|
||||
/// <summary>对象池复用时清空临时态。</summary>
|
||||
|
||||
@@ -53,7 +53,7 @@ namespace BaseGames.Enemies.Abilities
|
||||
var c = _candidates[i];
|
||||
if (Eligible(c, hasLOS, grounded)) total += Mathf.Max(0f, c.Weight);
|
||||
}
|
||||
if (total <= 0f) return SelectByPriority(hasLOS, grounded); // 权重全 0 → 退化为确定性取首个合格
|
||||
if (total <= 0f) return SelectByPriority(hasLOS, grounded); // 权重全 0 → 退化为按 Priority 选(并列取首个)
|
||||
float roll = Random.value * total;
|
||||
for (int i = 0; i < _candidates.Count; i++)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user