PD 보고: 점프 통과 동작 + 추가 의도 — '바닥에 깔린 상태가 아니라 걸쳐져서 지나가는 상황'
해석:
- 발판 위 착지(서있는) = 발판 영역 영역 X (정합)
- 그 외 (걷기·옆에서 닿음·점프·하강) = 통과
정정:
- UpdateContactFilterForDropThrough: Player 발 ↓ raycast(0.1m, Layer 16 mask) hit + IsGrounded → standingOnPlatform=true
- standingOnPlatform=true → Layer 16 mask 영역 ON (발판 영역 영역 X = 영역 영역 영역)
- 그 외 → Layer 16 mask OFF (걷기·점프·측면 모두 영역)
PrepareToJump 즉시 mask OFF (BT41) 영역 그대로 — 점프 시작 frame 영역 발판 영역 영역 차단
동작:
- 발판 위 정착 영역 = 영역 영역 ON = 안 떨어짐
- 발판 옆 걷기 영역 = footHit X 영역 OFF = 통과
- 점프 영역 영역 = IsGrounded=false 영역 standingOnPlatform=false → Layer 16 OFF = 통과
- 점프 후 발판 위 착지 = footHit + IsGrounded → standingOnPlatform=true → 다음 프레임 영역 영역 영역
PD 보고: 여전히 발판 통과 X (BT40 적용 정합이지만 동작 X)
진단:
- PrepareToJump frame: velocity.y = 0 (ComputeVelocity 영역 영역 영역 적용 X) → ascending=false → mask Layer 16 ON → body.Cast 발판 영역 충돌 → 영역 frame 영역 영역
- 다음 frame: velocity.y > 0 → mask OFF → 통과. 그러나 이미 영역 frame 영역 영역 영역
정정:
- PrepareToJump case 영역 영역 즉시 contactFilter mask Layer 16 OFF (frame 지연 차단)
- UpdateContactFilterForDropThrough: ascending = velocity.y > 0.01 || jumpState == Jumping (jumpState 영역 영역 영역 영역 영역 정합)
영역 frame 영역 PrepareToJump → Jumping 영역 영역 영역 mask 영역 OFF 유지 → body.Cast 영역 영역 영역 영역 영역
PD 지시: 개발팀과 논의 후 보고
개발팀장 Opus 직접 진단:
근본 원인:
- KinematicObject.Start()에서 contactFilter.SetLayerMask() 한 번 캐싱
- 이후 Physics2D.IgnoreLayerCollision으로 Layer Matrix 토글해도 contactFilter는 갱신 X
- body.Cast() raycast 영역 contactFilter 활용 = Layer Matrix 영역 무관
- 본 PM 19회 시도 모두 raycast 영역 미적용 = 발판 충돌 그대로 감지
해결 (Unity Kinematic2D 표준 Drop-Through 패턴):
- PlayerController.UpdateContactFilterForDropThrough — velocity.y > 0 (상승) 영역 Layer 16 mask 비활성
- contactFilter.SetLayerMask() 매 프레임 동적 갱신 = raycast가 발판 영역 무시
- GameOptimizer Physics2D.IgnoreLayerCollision(13, 16, false) 라인 폐기 (Layer Matrix 항시 ON 유지)
- BT39 Coroutine 영역 폐기
본 PM 자인:
- KinematicObject body.Cast() vs Rigidbody2D OnCollisionEnter 별도 경로 미인지
- ContactFilter2D 캐싱 동작 미인지
- 19회 시도 모두 Rigidbody collision callback 영역 (raycast 영역 무관)
동작:
- 점프 상승 (velocity.y > 0.01) → contactFilter mask Layer 16 비트 제거 → raycast 발판 영역 무시 → 통과
- 하강·정지 → mask 복원 → raycast 발판 영역 감지 → 착지
PD 보고: 발판 통과 X 여전 (BT38 매 프레임 토글 영역 동작 X)
진단:
- Unity Physics2D.IgnoreLayerCollision = 변경 즉시 적용 X, 다음 Physics step 영역만 적용 (한 frame 지연)
- Update에서 매 프레임 velocity.y 토글 → 점프 시작 frame 영역 영역 발판 영역 영역 충돌 발동 → 다음 frame 영역 통과 적용 → 이미 영역 영역
정정:
- UpdateJumpState 영역 PrepareToJump → StartCoroutine(JumpThroughRoutine)
- Coroutine: IgnoreLayerCollision(13, 16, true) → 0.3초 대기 → false 복구
- 0.3초 = 점프 정점 도달 시간 → 하강 시점 자동 충돌 ON → 착지 정합
- 매 프레임 Update 토글 영역 폐기
동작:
- 점프 시작 → 즉시 Layer 16 통과 (Coroutine 시작 + 0.3초 영역)
- 0.3초 후 (정점 도달·하강 시작) → 충돌 ON → 발판 위 착지
PD 보고: 발판 통과 X 여전 (BT35 PlatformEffector2D+Composite 영역 동작 X)
PD 제안: 충돌 로직 바꿔서 해결
표준 Drop-Through 패턴:
- Tilemap·Alien Layer 16 변환 (BT38)
- 기본: Player(13) ↔ JumpThrough(16) 충돌 ON = 정상 착지
- PlayerController.Update: velocity.y > 0.05 (상승) → IgnoreLayerCollision(13, 16, true) = 모든 발판 통과
- velocity.y <= 0.05 (하강·정지) → IgnoreLayerCollision(13, 16, false) = 충돌 ON = 착지
폐기:
- PlatformEffector2D·CompositeCollider2D·Rigidbody2D Static (BT35 영역)
- Layer 8·PlatformDropThrough Raycast (BT27·BT31 영역)
동작 (PD 의도 정합):
- Player 점프 상승 → 발판 모두 통과
- Player 하강 → 발판 위 착지
- 옆·아래에서 점프 → 통과 (상승 영역 모든 Layer 16 OFF)
PD 보고: 몬스터와 충돌 체크 X 통과 발생 — '충돌 로직 바꿔야'
자인:
- Distance 기반(hitRangeX=0.7, hitRangeY=1.0) = 빠른 통과 시 한 프레임 안 진입·이탈 = miss
- 표준 = Unity Physics Bounds.Intersects (AABB 정확)
정정:
- VisualBounds.Intersects(player.Bounds) — Enemy SpriteRenderer 영역 + Player Collider 영역 AABB 교차
- Layer 13↔14 OFF 영역 통과 가능 영역 그대로 (충돌 영역 무관)
- 시각 영역 보정(PLAYER_COLLIDER_TO_VISUAL_FOOT -0.17) 영역 그대로
- 빠른 통과 영역도 매 프레임 Bounds 교차 1회는 catch 정합
동작:
- Player가 Enemy 영역 통과 시 → Bounds 교차 시점 Schedule<PlayerEnemyCollision>
- 점프 상태(공중) 측면 → 피해 차단(BT35)
- 점프 후 머리 영역 → 밟기
PD 보고:
1. 밟기 시 측면 피해 발생 — [PEC] delta=-1.15~-0.41 stomped=False pInvuln=True
2. 발판 통과 X 여전 — [BT34-OneWay] applied=2 [Alien, Level] 적용 정합이지만 동작 X
진단:
- TilemapCollider2D + PlatformEffector2D 단독 = Unity 영역 동작 X
- Unity 표준 = TilemapCollider2D(compositeOperation=Merge) + CompositeCollider2D + Rigidbody2D(Static) + PlatformEffector2D 4종 조합
정정:
- PlayerEnemyCollision: stomped=False + !player.IsGrounded → 점프 측면 피해 차단 (PD 지시 방어 코드)
- GameOptimizer: TilemapCollider2D 영역에 CompositeCollider2D·Rigidbody2D Static·PlatformEffector2D 4종 조합 적용
동작:
- Player 위에서 발판 떨어짐 → 충돌 (착지)
- Player 옆·아래·점프 상승 → 통과
- Enemy 측면 충돌 시 점프 상태이면 피해 X
진단:
- [BT32-StartHit] dist=0.54 layer=8 정상 + Player 떨어짐 모순
- 원인: Physics2D.IgnoreLayerCollision(13, 8, true) Layer Matrix OFF + Physics2D.IgnoreCollision(c1, c2, false) 호출 충돌
- Unity Manual: Layer Matrix 영역 OFF면 개별 IgnoreCollision(false) 호출 무시
- 본 PM 영역 잘못: Layer 8 + Raycast 영역 표준 패턴 X
진정한 표준: PlatformEffector2D + useOneWay + surfaceArc 180
- 위에서 떨어지면 충돌(착지)
- 옆·아래·점프 상승 시 통과
- Layer 무관 (기본 Layer 0)
정정:
- IgnoreLayerCollision(13, 8) 폐기 (Layer 13 ↔ 14만 유지)
- 모든 일반 Collider(Tilemap 포함) PlatformEffector2D + useOneWay 적용
- Layer 8 잔존 → Layer 0 복원
- PlayerController PlatformDropThrough AddComponent → Destroy 대체
- PlatformDropThrough.cs 영역 동작 X (자동 제거)
[BT32-StartHit] dist=0.54 영역 = Player 시작 위치 0.54m 위. footRayDistance 0.5 영역 → 첫 Update raycast hit X(0.54>0.5) → else if 영역 → IgnoreCollision(true) 복구 → 통과 → 떨어짐
본 PM 자인:
- Start raycast 정상 활성 → 직후 Update raycast 거리 부족으로 hit miss
- else if 영역 = 발판 떠남 시 활성 해제 → Player 거리 잠시 벗어나도 활성 해제 = 떨어짐 직접 원인
정정:
- footRayDistance 0.5 → 1.0 (Player 시작 위치 영역 충분 커버)
- Update else if(falling && hit.collider==null && _activePlatform!=null) 영역 폐기 (활성 해제 = rising 시점만)
동작:
- Start 시 Level 영역 충돌 활성
- 떨어짐 영역 raycast 거리 일시 벗어나도 활성 유지 (떨어짐 차단)
- 점프(rising) 시 IgnoreCollision(true) 복구 = 통과
- 하강(falling) + 새 발판 hit → 새 발판 활성
[BT31-StartHit] 출력 0건 진단:
1. PlatformDropThrough 부착 X 또는 Awake/Start 호출 X
2. Start raycast 거리 0.5m 이내 발판 X (Player 시작 위치 발판 멀리)
진단 영역:
- Awake: [BT32-DropThrough] self/ko/mask 출력
- Start: [BT32-DropThrough] Start called + raycast 결과 출력
- hit Layer 8: [BT32-StartHit] dist·platform name·layer
- miss: [BT32-StartHit] no Layer 8 + 모든 Layer raycast로 anyHit 출력
- raycast 거리 무한대 (Mathf.Infinity)
[BT30-Collide] name='Level' layer=0 — Player 충돌 GameObject = Level Tilemap 확정.
PD 의도 = Level Tilemap 영역 전체 Drop-Through (점프 시 통과 + 하강 시 Raycast 착지)
본 PM 자인 (BT28 떨어짐 원인):
- Raycast 거리 0.1m 너무 짧음 → velocity 빠른 하강 시 miss
- 시작 시 즉시 활성 X → Player 시작 위치 발판 영역 통과 = 떨어짐
정정:
- GameOptimizer: TilemapCollider2D 제외 영역 폐기 → Level Tilemap도 Layer 8 변환
- PlatformDropThrough.Start: 시작 시 즉시 1회 raycast → Player 시작 위치 발판 영역 충돌 활성 (떨어짐 차단)
- PlatformDropThrough.Update: footRayDistance 0.1 → 0.5 + velocity 기반 동적 거리 (Mathf.Max + |vy|*deltaTime + 0.1)
동작:
- 시작 시 [BT31-StartHit] 출력 + Player 발판 위 정상 정착
- 점프 시 IgnoreCollision(true) 복구 = 통과
- 하강 시 raycast hit → IgnoreCollision(false) = 착지
PD 의도 정확 분석:
1. 발판 통과 = 발판 아래에서 위로 점프 시 막히지 않고 통과 (One-Way Platform)
2. 밟기 위치 = Player 시각 발이 Enemy 시각 머리 정확히 닿음
본 PM 자인:
- BT5-Dev #25부터 dyAtCollision = Player Collider 발 vs Enemy SpriteRenderer 머리 (시각 영역 보정 X)
- Player Collider Offset y +0.10 → Player Collider 발이 시각 발보다 0.17 위
- Enemy sprite 위 여백 ≈ 0 (EnemyIdle.png 동그란 sprite 영역)
- 시각 영역 정합 보정 미적용 = PD '여전히 떨어져있어' 보고 정합
정정:
- EnemyController.Update: footY = Bounds.min.y + (-0.17) → 시각 발 영역 보정
- PlayerEnemyCollision: STOMP_DELTA -0.4~-0.05 → -0.3~+0.05 (시각 영역 0 근처)
- PlayerController.OnCollisionEnter2D 진단 로그 — 발판 GameObject 영역 식별 (PD 영역 부딪힘 시 [BT30-Collide] 출력)
발판 영역 후속:
- PD가 발판 영역 부딪힐 때 Editor Console에 [BT30-Collide] name='?' layer=N 출력
- 본 PM이 직접 Editor.log read해서 발판 GameObject 영역 식별 + Layer 8 변환 의무
PD 보고: 게임 시작 시 Player 바닥으로 계속 떨어짐 — '점프 후 착지는 가능해야 한다고 했잖아'
본 PM 자인 (BT28 잘못):
- 모든 Collider(TilemapCollider2D 포함) Layer 8 변환 = 일반 지면도 Layer 8 = 통과 = 떨어짐
- 표준 platformer 영역 = 일반 지면(Layer 0) + 발판(Layer 8) 분리 의무
정정:
- TilemapCollider2D 제외 영역 복원 → Level Tilemap = Layer 0 = 일반 충돌 = 착지 정합
- Foreground GameObject(TilemapRenderer만·Collider 미부착) 영역에 TilemapCollider2D 동적 추가 + Layer 8 변환 → 발판 정합
동작:
- Level Tilemap = 일반 지면 (Layer 0) = Player 정상 착지·이동
- Foreground Tilemap = 발판 (Layer 8) = 기본 통과 + Player 발 Raycast 시 Drop-Through 착지
- 별개 BoxCollider2D(Alien 등) = Layer 8 = 발판 정합
PD 보고:
1. 발판 통과 X — Tilemap Layer 0 그대로 → 일반 충돌 → 점프 통과 X
2. 밟기 위치 너무 높음 — STOMP_DELTA_MAX +0.1 → 시각 발이 Enemy 머리 위 0.1 떠 있음
데이터 진단:
- [BT27-JumpThrough] applied=1 (Alien only) — Tilemap 제외로 발판 영역 미적용
- [PEC] stomped=True delta=-0.11~-0.28 — Collider 영역만 정합 / 시각 영역 차이 0.2
정정:
- GameOptimizer: TilemapCollider2D 제외 영역 폐기 → 모든 일반 Collider Layer 8 변환
- PlayerEnemyCollision: STOMP_DELTA -0.3~+0.1 → -0.4~-0.05 (Player Collider Offset +0.10 + Enemy sprite 위 여백 0.1 보정)
Drop-Through 패턴 동작:
- 모든 지면·발판 Layer 8 = 기본 통과 (Player 13 ↔ Layer 8 IgnoreLayerCollision)
- Player 하강 + 발 Raycast hit → IgnoreCollision(false) 임시 활성 = 착지
- 점프(상승) → IgnoreCollision(true) 복구 = 통과
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 등 점프 가능 발판 영역 영역만)
본 PM 자인 (C5·C39·C44):
- BT5-Dev #1~#21 동안 Enemy.prefab m_Layer/m_TagString 영역 검증 X 누적
- Enemy의 m_Layer=13 (Player와 동일) + m_TagString=Player (Player tag 중복) = 진정한 근본
→ FindGameObjectWithTag("Player")가 Enemy 발견 + Layer 동일로 IgnoreCollision도 효과 X
- 본 PM이 추측·Bounds·Distance·IgnoreCollision·OneWay 영역 모두 = 도달 영역 외 정정
정정:
- Enemy.prefab m_Layer 13→14
- Enemy.prefab m_TagString Player→Untagged
- GameOptimizer Physics2D.IgnoreLayerCollision(13, 14, true) BeforeSceneLoad
영구 효과:
- FindGameObjectWithTag("Player") = Player.prefab만 발견 정합
- Player Layer 13 ↔ Enemy Layer 14 충돌 OFF = 통과 정합
- IgnoreCollision instance 영역 의존 X = 안전
본 PM이 외부 영역에서 변경한 BT5-Dev 모든 영역을 EerieVillage git에 반영:
- EnemyController.cs (Distance 기반 감지·VisualBounds·IgnoreCollision·Bounds)
- PlayerEnemyCollision.cs (dyAtCollision·stomped 판정)
- PlayerController.cs (LastGroundedPosition·OnHealthDeath/Resurrect·자동 컴포넌트)
- DeathZone.cs (Coroutine·viewport 외 대기)
- Health.cs (invulnerableDuration 0.5·resurrectInvulnerableDuration 2.0·GrantInvulnerability·이벤트 3종)
- GameOptimizer.cs (신설·targetFrameRate·queriesHitTriggers·SetupOneWayPlatforms)
- PlayerInvulnerabilityFlash.cs (신설)
- ResurrectPromptUI.cs (신설)
- Player.prefab (Collider Size·Offset·m_FlipX 1)
- Enemy.prefab (m_IsTrigger 0)
- Hero1 sprite meta (combatidle 4종 rename)
- _archive/ 폴더 + 9 sprite 이동
- bak_2026* 28 파일 전수 삭제 (D 옵션)
원인 자인:
- 본 PM이 Unity 외부 영역 변경했지만 EerieVillage git commit X 영역 누적 = PD Editor에 도달 X = 옛 코드 동작
- C5·C44 위배
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>