BT5-Dev #68: 점프 X·Y 분리 + TileGround* 벽 자동 분류 제외 (PD 2종 명시 채택)

PD 명시 (2026-05-08):
1. "대각선으로 점프로 벽 부분을 통과하려는 상황 → Player 점프 상태에서 밀려나는 현상" (애초에 통과 X 의무)
2. "전진하며 점프할 경우 앞이 막혀있으면 위로만 점프되어야 하는데 점프 자체가 막힘" (앞 막혀도 정상 점프 의무)

본 PM 직접 read 진단:

버그 1 (벽 통과) 원인:
- 자동 분류 영역(BT47/BT48)이 TileGround·TileGroundDark·TileGroundTop도 AutoForeground로 이동
- AutoForeground = Layer 16 + Drop-Through 패턴 (ascending mask OFF)
- = 대각선 점프 시 벽 Tile 통과 가능

버그 2 (점프 막힘) 원인:
- KinematicObject.PerformMovement line 164~165:
  velocity.x *= 0;  velocity.y = Mathf.Min(velocity.y, 0);
- = X 이동 시점 hit (앞 벽)에서도 velocity.y 영점 강제
- = 점프 시작 시 앞 벽 hit → 점프 속도 0 → 점프 자체 차단

정정:

1. KinematicObject.cs (버그 2):
   - 공중 hit 처리 X·Y 분리:
     - X 이동 시점 hit (앞 벽) → velocity.x = 0, velocity.y 보존 (점프 속도 유지)
     - Y 이동 시점 hit (천장) → velocity.x·y 모두 cap (기존)

2. GameOptimizer.cs (버그 1):
   - TileGround* (3종 — 지면·벽 의도) 자동 분류 제외 추가
   - tileAsset.name.StartsWith("TileGround") → continue
   - TileGround·TileGroundDark·TileGroundTop = Level 잔존·Layer 0·영구 충돌·통과 X

효과:
- 버그 1: 벽 통과 X (TileGround* = Layer 0 영구 충돌)
- 버그 2: 앞 막혀도 위로 점프 정합 (Y 속도 보존)
- 발판 동작 그대로 (TileFloating·MidgroundFiller·Building·cloud·hillside·midground·mountains 자동 분류)
- 나무·plant·fence·house 자체 통과 그대로

후속 의무:
- PD Refresh+Play 시각 검증 (대각선 점프 벽 통과 X + 앞 막힌 점프 작동)
- 본 PM Editor.log [BT48-MoveTiles] direct read
This commit is contained in:
깃 관리자 2026-05-08 00:20:53 +09:00
parent 835f572e95
commit c9b39c4373
2 changed files with 10 additions and 4 deletions

View File

@ -133,11 +133,15 @@ namespace Platformer.Mechanics
if (!levelTilemap.HasTile(pos)) continue; if (!levelTilemap.HasTile(pos)) continue;
// BT63 — Tile asset의 m_ColliderType=None = 배경 의도 (tree·plant·fence·house) = 자동 분류 제외 // BT63 — Tile asset의 m_ColliderType=None = 배경 의도 (tree·plant·fence·house) = 자동 분류 제외
// BT48 시점 + 나무 충돌 정정만 추가 (PD 명시 채택 2026-05-07).
// 결과: 나무·plant·fence·house Tile은 Level 잔존·자체 None Collider로 자연 통과. // 결과: 나무·plant·fence·house Tile은 Level 잔존·자체 None Collider로 자연 통과.
var tileAsset = levelTilemap.GetTile<UnityEngine.Tilemaps.Tile>(pos); var tileAsset = levelTilemap.GetTile<UnityEngine.Tilemaps.Tile>(pos);
if (tileAsset != null && tileAsset.colliderType == UnityEngine.Tilemaps.Tile.ColliderType.None) continue; if (tileAsset != null && tileAsset.colliderType == UnityEngine.Tilemaps.Tile.ColliderType.None) continue;
// BT68 — TileGround* (지면·벽 의도) 자동 분류 제외 (PD 보고 2026-05-08: "대각선 점프로 벽 통과")
// 결과: TileGround·TileGroundDark·TileGroundTop Tile은 Level 잔존·Layer 0 영구 충돌·통과 X.
string nm = tileAsset != null ? tileAsset.name : string.Empty;
if (nm.StartsWith("TileGround")) continue;
Vector3 worldPos = levelTilemap.CellToWorld(pos); Vector3 worldPos = levelTilemap.CellToWorld(pos);
bool aboveThreshold = worldPos.y >= airThresholdY; bool aboveThreshold = worldPos.y >= airThresholdY;
bool isSmallAir = !aboveThreshold && IsSmallAirPlatform(levelTilemap, pos, MAX_PLATFORM_WIDTH); bool isSmallAir = !aboveThreshold && IsSmallAirPlatform(levelTilemap, pos, MAX_PLATFORM_WIDTH);

View File

@ -160,9 +160,11 @@ namespace Platformer.Mechanics
} }
else else
{ {
//We are airborne, but hit something, so cancel vertical up and horizontal velocity. // BT68 — X·Y 분리 처리 (PD 보고 2026-05-08: "전진 점프 시 앞 막혀도 위로 점프 가능 의무"):
velocity.x *= 0; // X 이동 시점 hit (앞 벽) → velocity.x만 0, velocity.y 보존 (점프 속도 유지)
velocity.y = Mathf.Min(velocity.y, 0); // Y 이동 시점 hit (천장) → velocity.x·y 모두 cap (기존 동작)
velocity.x = 0;
if (yMovement) velocity.y = Mathf.Min(velocity.y, 0);
} }
//remove shellDistance from actual move distance. //remove shellDistance from actual move distance.
var modifiedDistance = hitBuffer[i].distance - shellRadius; var modifiedDistance = hitBuffer[i].distance - shellRadius;