fix(enemy): 冲锋禁止以中心悬空姿态收尾(会导致导航映射失败/巡逻失效)
新增 EnemyMovement.IsCenterOverGround() 与 RushAbility.SettleRoutine: 冲锋结束时若着地却中心悬在崖外,继续朝原方向推进直到离地(自由落体)或中心重回地面上方; 有时限,超时仍未脱离则告警暴露地形问题(崖沿有墙),不静默留下坏站位。
This commit is contained in:
@@ -21,6 +21,9 @@ namespace BaseGames.Enemies.Abilities
|
||||
/// 悬崖:冲锋期间**允许越过崖沿**(经 <see cref="EnemyMoveInput.AllowLedgeCross"/> 放开移动层的悬崖夹紧),
|
||||
/// 敌人会冲出平台边缘并按重力下落、空中保持水平冲速,而不是停在崖边悬空。
|
||||
///
|
||||
/// <b>收尾不变量</b>:冲锋结束时**绝不允许**停在"着地但身体中心悬在崖外"的姿态——
|
||||
/// 该姿态会让导航无法把敌人映射到可行走段,导致巡逻/寻路失效。由 SettleRoutine 保证(见其说明)。
|
||||
///
|
||||
/// 冲锋动画由本能力全权驱动(步态不抢动画)。身体接触伤害与本能力解耦:
|
||||
/// 由常驻的 <see cref="BodyContactDamage"/> 全程负责,本能力不开关它。
|
||||
/// </summary>
|
||||
@@ -32,6 +35,9 @@ namespace BaseGames.Enemies.Abilities
|
||||
private const float StuckWindowSeconds = 0.15f;
|
||||
private const float StuckMinProgress = 0.05f;
|
||||
|
||||
// 落位收敛的最长额外推进时长(秒):用于脱离"中心悬在崖外"的非法收尾姿态
|
||||
private const float SettleMaxSeconds = 0.5f;
|
||||
|
||||
protected override void Awake()
|
||||
{
|
||||
base.Awake();
|
||||
@@ -78,6 +84,7 @@ namespace BaseGames.Enemies.Abilities
|
||||
_animancer.Play(_cfg.loopClip);
|
||||
|
||||
yield return RushRoutine(dir, lockX, speed, mv);
|
||||
yield return SettleRoutine(dir, speed, mv); // 收尾姿态必须合法:中心不得悬在崖外
|
||||
|
||||
_enemy.StopMovement();
|
||||
|
||||
@@ -126,6 +133,30 @@ namespace BaseGames.Enemies.Abilities
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 落位收敛:**禁止**冲锋以"着地但身体中心悬在崖外"的姿态收尾。
|
||||
/// <para>该姿态下碰撞体后半截压在平台角上、物理会把敌人托住(刚体冻结旋转),看似停稳,
|
||||
/// 但导航无法把此位置映射到可行走段,会让巡逻/寻路彻底失效。</para>
|
||||
/// <para>处理:继续朝原方向推进,直到离地(转入自由落体,随后正常落地)或中心重回地面上方。
|
||||
/// 有时限;若到时仍未脱离(多为崖沿处有墙把敌人卡住的地形问题),显式告警暴露根因,不静默留下坏站位。</para>
|
||||
/// </summary>
|
||||
private IEnumerator SettleRoutine(float dir, float speed, EnemyMovement mv)
|
||||
{
|
||||
if (mv == null) yield break;
|
||||
|
||||
float t = 0f;
|
||||
while (mv.IsGrounded && !mv.IsCenterOverGround() && t < SettleMaxSeconds)
|
||||
{
|
||||
_enemy.MoveInDirectionWithSpeed(dir, speed, allowLedgeCross: true);
|
||||
yield return null;
|
||||
t += Time.deltaTime;
|
||||
}
|
||||
|
||||
if (mv.IsGrounded && !mv.IsCenterOverGround())
|
||||
Debug.LogWarning($"[RushAbility] '{_enemy.name}' 冲锋收尾时身体中心悬在崖外且无法脱离" +
|
||||
"(多为崖沿处存在墙体阻挡)。该站位会使导航无法映射到可行走段,巡逻将失效——请检查该处地形。", this);
|
||||
}
|
||||
|
||||
protected override void OnInterrupted(InterruptReason reason)
|
||||
{
|
||||
// 丢失目标 = AI 主动退出(ExternalRequest) → 播收招 Skill_End;
|
||||
|
||||
Reference in New Issue
Block a user