From d15a46b5ccd22a5060dd27f67a202c28430d9830 Mon Sep 17 00:00:00 2001 From: swrring Date: Thu, 7 May 2026 16:42:31 +0900 Subject: [PATCH] =?UTF-8?q?BT5-Dev=20#25:=20Bounds=20=EA=B8=B0=EB=B0=98=20?= =?UTF-8?q?footHeadDelta=20+=20Tilemap=20OneWay=20=ED=8F=90=EA=B8=B0=20(PD?= =?UTF-8?q?=20=EC=9D=98=EB=8F=84=20=EC=A0=95=ED=95=A9)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PD 보고: 1. 점프 밟기 위치 너무 높음 — dyAtCollision = transform 차 (center vs center) 영역 잘못 2. 발판 통과 X — Tilemap OneWay 영역 적용 = 모든 Tile 영역 OneWay = 일반 지면 영역 깨짐 정정: - EnemyController.Update: dyAtCollision = Player.Bounds.min.y - Enemy.VisualBounds.max.y (footHeadDelta) - PlayerEnemyCollision: stomped = (-0.2 < delta < 0.3) — Player 발 ≈ Enemy 머리 영역 - GameOptimizer: TilemapCollider2D 영역 영역 OneWay 영역 영역 폐기 → 별개 BoxCollider2D 영역 OneWay (Alien 등 점프 가능 발판 영역 영역만) --- Assets/Scripts/Gameplay/PlayerEnemyCollision.cs | 16 +++++++++------- Assets/Scripts/Mechanics/EnemyController.cs | 13 +++++++------ Assets/Scripts/Mechanics/GameOptimizer.cs | 10 ++++++---- 3 files changed, 22 insertions(+), 17 deletions(-) diff --git a/Assets/Scripts/Gameplay/PlayerEnemyCollision.cs b/Assets/Scripts/Gameplay/PlayerEnemyCollision.cs index 59a5997..7959412 100644 --- a/Assets/Scripts/Gameplay/PlayerEnemyCollision.cs +++ b/Assets/Scripts/Gameplay/PlayerEnemyCollision.cs @@ -21,9 +21,12 @@ namespace Platformer.Gameplay /// BT5-Dev #16 — EnemyController.Update에서 측정한 Player·Enemy y 차 (밟기 판정 영역). public float dyAtCollision; - // BT5-Dev #24 — 실측 (Editor.log): 점프 정점 dy 최댓값 0.95. STOMP_MIN_DY 1.0은 도달 X = stomped 영원히 X. - // 0.7 = dy 0.95 영역에서 영역 발동 + 측면 dy 0.15 영역에서 발동 X (정합) - const float STOMP_MIN_DY = 0.7f; + // BT5-Dev #25 — dyAtCollision 영역 = footHeadDelta (Player 발 - Enemy 머리) + // 0 = 닿음 / 양수 = Player 발이 Enemy 머리 위 / 음수 = Player 발이 Enemy 머리 영역 안 영역 + // 측면 충돌 시 footHeadDelta 음수 (Player 발 영역 < Enemy 머리 영역) + // 점프 밟기 시 footHeadDelta -0.2 ~ +0.3 영역 (착지 직전·직후) + const float STOMP_DELTA_MIN = -0.2f; // Enemy 머리 영역 영역 영역 영역 영역 영역 영역 + const float STOMP_DELTA_MAX = 0.3f; // Enemy 머리 영역 영역 영역 영역 영역 영역 영역 PlatformerModel model = Simulation.GetModel(); @@ -31,11 +34,10 @@ namespace Platformer.Gameplay { if (player == null || player.health == null || enemy == null) return; - // BT5-Dev #21 — 밟기 영역: Player 발이 Enemy 영역 위 (체공 상승·하강 모두 영역 — vy 조건 폐기) - // dy > STOMP_MIN_DY 영역에서 점프 영역 보장됨 (측면 닿음 영역 dy ≈ 0). vy<0 조건은 상승 시점 측면 피격 오인 발동 - bool stomped = dyAtCollision > STOMP_MIN_DY; + // BT5-Dev #25 — Player 발이 Enemy 머리 영역 영역 영역 영역 발동 (footHeadDelta 영역 영역 영역 영역) + bool stomped = dyAtCollision > STOMP_DELTA_MIN && dyAtCollision < STOMP_DELTA_MAX; - Debug.Log($"[PEC] stomped={stomped} dy={dyAtCollision:F2} vy={player.velocity.y:F2} (thr>{STOMP_MIN_DY}) pInvuln={player.health.IsInvulnerable}"); + Debug.Log($"[PEC] stomped={stomped} delta={dyAtCollision:F2} (range {STOMP_DELTA_MIN}~{STOMP_DELTA_MAX}) pInvuln={player.health.IsInvulnerable}"); if (stomped) { diff --git a/Assets/Scripts/Mechanics/EnemyController.cs b/Assets/Scripts/Mechanics/EnemyController.cs index 5e580d2..00e151b 100644 --- a/Assets/Scripts/Mechanics/EnemyController.cs +++ b/Assets/Scripts/Mechanics/EnemyController.cs @@ -108,18 +108,19 @@ namespace Platformer.Mechanics } if (_cachedPlayer != null && _cachedPlayer.health != null && _cachedPlayer.health.IsAlive) { - // BT5-Dev #16 — Distance 기반 단순 감지 (Bounds 영역 산수 영역 의존 X·항상 작동) - // dx 0.7·|dy| 1.0 = 표준 platformer Enemy/Player 닿음 영역. dy > 0.5 = Player가 Enemy 위에서 밟음. + // BT5-Dev #25 — Bounds 기반 dy: Player 발 vs Enemy 머리 영역 (PD 의도 정합) Vector3 ePos = transform.position; Vector3 pPos = _cachedPlayer.transform.position; float dx = Mathf.Abs(pPos.x - ePos.x); - float dy = pPos.y - ePos.y; + float footY = _cachedPlayer.Bounds.min.y; // Player 발 world y + float headY = VisualBounds.max.y; // Enemy 머리 world y + float footHeadDelta = footY - headY; // 0 = 닿음 / 양수 = Player 발 위 / 음수 = Player 발 아래 - bool inRange = dx < hitRangeX && Mathf.Abs(dy) < hitRangeY; + bool inRange = dx < hitRangeX && Mathf.Abs(pPos.y - ePos.y) < hitRangeY; if (inRange != _diagWasIntersecting) { - Debug.Log($"[EnemyDiag@{name}] inRange={inRange} dx={dx:F2} dy={dy:F2} (thresholds dx<{hitRangeX} |dy|<{hitRangeY}) | ePos={ePos} pPos={pPos}"); + Debug.Log($"[EnemyDiag@{name}] inRange={inRange} footHeadDelta={footHeadDelta:F2} dx={dx:F2}"); _diagWasIntersecting = inRange; } @@ -128,7 +129,7 @@ namespace Platformer.Mechanics var ev = Schedule(); ev.player = _cachedPlayer; ev.enemy = this; - ev.dyAtCollision = dy; + ev.dyAtCollision = footHeadDelta; } } } diff --git a/Assets/Scripts/Mechanics/GameOptimizer.cs b/Assets/Scripts/Mechanics/GameOptimizer.cs index e03960f..30de1fb 100644 --- a/Assets/Scripts/Mechanics/GameOptimizer.cs +++ b/Assets/Scripts/Mechanics/GameOptimizer.cs @@ -29,15 +29,17 @@ namespace Platformer.Mechanics [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterSceneLoad)] static void SetupOneWayPlatforms() { + // BT5-Dev #25 — Tilemap 영역 OneWay 영역 폐기 (모든 Tile 영역 OneWay = 일반 지면 영역도 영역 = 게임 영역 깨짐) + // 별개 BoxCollider2D 영역 영역 영역 영역 영역 영역 발판 영역 영역 OneWay 영역 영역 적용 int applied = 0; - int excludedTrigger = 0, excludedActor = 0; + int excludedTrigger = 0, excludedActor = 0, excludedTilemap = 0; var allColliders = Object.FindObjectsByType(FindObjectsSortMode.None); var appliedNames = new System.Collections.Generic.List(); - var excludedNames = new System.Collections.Generic.List(); foreach (var c in allColliders) { if (c == null) continue; if (c.isTrigger) { excludedTrigger++; continue; } + if (c.GetComponent() != null) { excludedTilemap++; continue; } // BT25 — Tilemap 영역 영역 영역 일반 충돌 영역 if (c.GetComponent() != null || c.GetComponent() != null || c.GetComponent() != null @@ -60,8 +62,8 @@ namespace Platformer.Mechanics applied++; if (appliedNames.Count < 8) appliedNames.Add($"{c.gameObject.name}({c.GetType().Name})"); } - Debug.Log($"[BT21-OneWay] applied={applied} trigger={excludedTrigger} actor={excludedActor} total={allColliders.Length}"); - Debug.Log($"[BT21-OneWay] appliedSamples=[{string.Join(", ", appliedNames)}]"); + Debug.Log($"[BT25-OneWay] applied={applied} trigger={excludedTrigger} tilemap={excludedTilemap} actor={excludedActor} total={allColliders.Length}"); + Debug.Log($"[BT25-OneWay] appliedSamples=[{string.Join(", ", appliedNames)}]"); } } }