diff --git a/Assets/Scripts/Mechanics/EnemyController.cs b/Assets/Scripts/Mechanics/EnemyController.cs index 626044a..58a45ff 100644 --- a/Assets/Scripts/Mechanics/EnemyController.cs +++ b/Assets/Scripts/Mechanics/EnemyController.cs @@ -316,8 +316,8 @@ namespace Platformer.Mechanics // BT90 — 수평 Raycast 영역 폐기 (BT89 거짓 양성 — 같은 Tile cell 영역 검출) // 벽 영역 = stuckTimer 영역 (50ms 정지 시 즉시 phase+2)으로 처리 - // BT12-Dev 2026-05-12 — cliffCheck Enemy 영역 가장자리 상대 (PD: 발판 가장자리 걸쳐 대기 정정) - // 절대 cliffCheckDistance 폐기·bounds.extents.x + edgeMargin 사용 → Enemy 영역 바로 앞 검사 + // BT12-Dev 2026-05-12 — cliffCheck Trigger 제외 (PD: CinemachineConfiner Trigger 영역 false positive 정정) + // ContactFilter2D useTriggers=false·useLayerMask=true·실제 발판/바닥 Solid Collider만 hit if (_collider != null) { const float EDGE_MARGIN = 0.15f; @@ -325,11 +325,17 @@ namespace Platformer.Mechanics float backX = _collider.bounds.center.x - moveDir * (_collider.bounds.extents.x + EDGE_MARGIN); float footY = _collider.bounds.min.y + 0.05f; - RaycastHit2D groundHitFwd = Physics2D.Raycast(new Vector2(fwdX, footY), Vector2.down, cliffCheckDepth, groundLayerMask); - if (groundHitFwd.collider == null) + var cf = new ContactFilter2D(); + cf.useTriggers = false; + cf.useLayerMask = true; + cf.layerMask = groundLayerMask; + var hits = new RaycastHit2D[1]; + + int fwdCount = Physics2D.Raycast(new Vector2(fwdX, footY), Vector2.down, cf, hits, cliffCheckDepth); + if (fwdCount == 0) { - RaycastHit2D groundHitBack = Physics2D.Raycast(new Vector2(backX, footY), Vector2.down, cliffCheckDepth, groundLayerMask); - if (groundHitBack.collider == null) + int backCount = Physics2D.Raycast(new Vector2(backX, footY), Vector2.down, cf, hits, cliffCheckDepth); + if (backCount == 0) { // 양측 cliff — 제자리 대기 if (control != null) control.move.x = 0f;