diff --git a/Assets/Scripts/Mechanics/DeathZone.cs b/Assets/Scripts/Mechanics/DeathZone.cs
index 3cb30a0..bf4edf1 100644
--- a/Assets/Scripts/Mechanics/DeathZone.cs
+++ b/Assets/Scripts/Mechanics/DeathZone.cs
@@ -47,10 +47,10 @@ namespace Platformer.Mechanics
yield return null;
}
- // 위치 복귀 + HP 감소 + 1초 무적
+ // 위치 복귀 + HP 감소 + 1초 무적 (PD 지시 2026-05-07 — 낙사 복귀 시 hit 모션 X → DecrementSilent)
p.transform.position = p.LastGroundedPosition;
p.velocity = Vector2.zero;
- p.health.Decrement(fallDamage);
+ p.health.DecrementSilent(fallDamage);
if (p.health.IsAlive)
{
diff --git a/Assets/Scripts/Mechanics/EnemyController.cs b/Assets/Scripts/Mechanics/EnemyController.cs
index 2b25fd0..eadbf4a 100644
--- a/Assets/Scripts/Mechanics/EnemyController.cs
+++ b/Assets/Scripts/Mechanics/EnemyController.cs
@@ -19,8 +19,8 @@ namespace Platformer.Mechanics
public float hitRangeX = 0.7f;
/// Y 임계값. 위/아래 둘 다 인정.
public float hitRangeY = 1.0f;
- /// 밟기 판정 — Player가 Enemy보다 위 거리.
- public float stompMinDy = 0.5f;
+ /// 밟기 판정 — Player가 Enemy보다 위 거리. 발 닿는 느낌 영역(0.05~0.15).
+ public float stompMinDy = 0.1f;
internal PatrolPath.Mover mover;
internal AnimationController control;
diff --git a/Assets/Scripts/Mechanics/GameOptimizer.cs b/Assets/Scripts/Mechanics/GameOptimizer.cs
index 453def1..5d6b2e7 100644
--- a/Assets/Scripts/Mechanics/GameOptimizer.cs
+++ b/Assets/Scripts/Mechanics/GameOptimizer.cs
@@ -18,15 +18,26 @@ namespace Platformer.Mechanics
}
///
- /// PD 지시 2026-05-07 — 모든 TilemapCollider2D를 One-Way Platform으로 자동 변환.
- /// 위에서만 착지·측면·아래 통과 = 점프 시 천장 통과 + 이동 시 측면 벽 통과 + 착지/걷기는 지면 위 머무름.
+ /// PD 지시 2026-05-07 — 모든 지형 Collider2D를 One-Way Platform으로 자동 변환.
+ /// 위에서만 착지·측면·아래 통과. Player·Enemy·DeathZone·VictoryZone·TokenInstance·Trigger Collider 영역 제외.
///
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterSceneLoad)]
static void SetupOneWayPlatforms()
{
- var tilemapColliders = Object.FindObjectsByType(FindObjectsSortMode.None);
- foreach (var c in tilemapColliders)
+ int applied = 0;
+ var allColliders = Object.FindObjectsByType(FindObjectsSortMode.None);
+ foreach (var c in allColliders)
{
+ if (c == null) continue;
+ if (c.isTrigger) continue;
+ // Player·Enemy·기타 GameObject 영역 제외
+ if (c.GetComponent() != null) continue;
+ if (c.GetComponent() != null) continue;
+ if (c.GetComponent() != null) continue;
+ if (c.GetComponent() != null) continue;
+ if (c.GetComponent() != null) continue;
+ if (c.GetComponent() != null) continue;
+
c.usedByEffector = true;
var effector = c.GetComponent();
if (effector == null) effector = c.gameObject.AddComponent();
@@ -35,7 +46,9 @@ namespace Platformer.Mechanics
effector.rotationalOffset = 0f;
effector.useSideFriction = false;
effector.useSideBounce = false;
+ applied++;
}
+ Debug.Log($"[BT19-OneWay] applied={applied} totalColliders={allColliders.Length}");
}
}
}
diff --git a/Assets/Scripts/Mechanics/Health.cs b/Assets/Scripts/Mechanics/Health.cs
index ae89918..f33c43f 100644
--- a/Assets/Scripts/Mechanics/Health.cs
+++ b/Assets/Scripts/Mechanics/Health.cs
@@ -188,6 +188,33 @@ namespace Platformer.Mechanics
/// SOT: 캐릭터_리소스_규칙_v1.md §3.1.4 death → resurrection 시퀀스.
/// BT7-Plan 영역: 부활 시 maxHP 회복 룰 — 현재 전체 회복, 향후 부분 회복 룰 결정 시 Resurrect(int) 오버로드 추가.
///
+ ///
+ /// 시스템 페널티 영역 — hit Animator 영역 발동 X 영역 단순 HP 감소. 낙사 복귀 영역·환경 데미지 영역 등.
+ /// PD 지시 2026-05-07 — 낭떠러지 복귀 시 hit 모션 재생 X.
+ ///
+ public void DecrementSilent(int damage)
+ {
+ if (damage <= 0) return;
+ if (Time.time < invulnerableUntil) return;
+
+ currentHP = Mathf.Clamp(currentHP - damage, 0, maxHP);
+ if (invulnerableDuration > 0f) invulnerableUntil = Time.time + invulnerableDuration;
+
+ if (currentHP > 0)
+ {
+ // hit Animator Trigger 영역 X (영역 핵심 차이) — OnDamagedEvent만 발화
+ OnDamagedEvent?.Invoke(damage);
+ }
+ if (currentHP == 0)
+ {
+ var animator = GetComponent();
+ if (animator != null) animator.SetBool("dead", true);
+ OnDeathEvent?.Invoke();
+ var ev = Schedule();
+ ev.health = this;
+ }
+ }
+
///
/// 외부 시스템이 임시 무적 시간을 부여 (낙사 위치 복귀·체크포인트 등). 기존 i-frame과 비교해 더 긴 시간을 채택.
/// PD 지시 2026-05-07 — 낙사 시 1초 무적.