@
fix(enemy): 巡逻边缘不越界 + 卡死兜底 + Locomotion 惰性发现 - WouldBlockAhead(EnemyMovement):按请求方向从碰撞体前缘(bounds.max/min.x) 即时射线判墙/悬崖,天然考虑碰撞体宽度;MoveHorizontal 据此夹紧前进,保证 "碰撞体边缘停在地形边缘、不越界"。移动层夹紧与 Pace 翻向共用同一判定, 避免"夹停却不掉头"。nav 走 MoveWithSpeed 不受影响。 - Pace 加窗口净位移卡死兜底:撞上未挂检测层的墙/卡角(含贴墙微抖)也能翻向, 用净位移而非逐帧差以免微抖重置计数。 - EnemyBase.Locomotion 改惰性发现:关域重载下 Awake 设的实例字段可能残留 为 null,首次访问按需补发现,编辑器/构建都不为空(此前致入口态偶发 NRE)。 PlayMode(跨调用取样,避免 Thread.Sleep 冻结主线程)验证:Pace 来回踱步、 遇边缘/墙掉头、碰撞体不越界。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> @
This commit is contained in:
@@ -226,6 +226,35 @@ namespace BaseGames.Enemies
|
||||
return new Vector2(x, b.min.y);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 朝 <paramref name="dir"/> 前进是否会撞墙或让碰撞体前缘越过地形边缘。
|
||||
/// 用碰撞体前缘(bounds.max.x / min.x)判定,天然考虑碰撞体宽度——
|
||||
/// 保证"碰撞体边缘不越过地形边缘"。用当前请求方向即时射线,避免缓存朝向过期。
|
||||
/// 供移动层夹紧与巡逻 Pace 翻向共用同一判定,避免"夹停了却不掉头"。
|
||||
/// </summary>
|
||||
public bool WouldBlockAhead(float dir)
|
||||
{
|
||||
var col = _groundCheckCollider != null ? _groundCheckCollider : GetComponent<Collider2D>();
|
||||
if (col == null) return false;
|
||||
Bounds b = col.bounds;
|
||||
float sign = Mathf.Sign(dir);
|
||||
float edgeX = sign >= 0f ? b.max.x : b.min.x; // 朝向侧碰撞体前缘
|
||||
LayerMask wallLayer = (_wallMask.value != 0) ? _wallMask : _groundMask;
|
||||
|
||||
// 墙:从前缘水平探;命中则前方有墙
|
||||
if (_wallCheckDist > 0f &&
|
||||
Physics2D.Raycast(new Vector2(edgeX, b.center.y), new Vector2(sign, 0f), _wallCheckDist, wallLayer))
|
||||
return true;
|
||||
|
||||
// 悬崖:从"前缘 + 前探偏移"处向下探地;无地面则前缘外是悬崖
|
||||
if (_ledgeCheckDownDist > 0f &&
|
||||
!Physics2D.Raycast(new Vector2(edgeX + sign * _ledgeCheckFwdOffset, b.min.y),
|
||||
Vector2.down, _ledgeCheckDownDist, _groundMask))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void WallAndLedgeCheck()
|
||||
{
|
||||
LayerMask wallLayer = (_wallMask.value != 0) ? _wallMask : _groundMask;
|
||||
@@ -375,7 +404,9 @@ namespace BaseGames.Enemies
|
||||
public void MoveHorizontal(float dir)
|
||||
{
|
||||
if (_isTurning) return;
|
||||
UpdateFacing(dir);
|
||||
if (dir != 0f) UpdateFacing(dir); // 先朝请求方向(视觉转身),即使随后停步
|
||||
// 地面怪:前缘将越过地形边缘/撞墙则不前进(碰撞体边缘停在地形边缘,不越界)
|
||||
if (dir != 0f && IsGrounded && WouldBlockAhead(dir)) dir = 0f;
|
||||
var vel = _rb.velocity;
|
||||
vel.x = dir * _config.WalkSpeed;
|
||||
_rb.velocity = vel;
|
||||
|
||||
Reference in New Issue
Block a user