BT5-Dev #49: 배경 Tile (tree·cloud) 충돌 차단 — Tile asset m_ColliderType 존중

근본 원인:
- BT47 line 106 `SetColliderType(pos, Sprite)` 무차별 강제
- tree.asset `m_ColliderType: 0` (None — 배경 의도) 무시 → 발판처럼 충돌

표준 패턴 정정 (3종 결합):
1. 분류 단계: Tile asset이 ColliderType.None = Foreground 이동 차단 (Level 잔존)
2. Foreground 이동 시: Tile asset 원래 colliderType 존중 (None=배경 / Sprite=발판)
3. Foreground 사후 복원: 이미 그려진 None Tile = SetColliderType(None) + ProcessTilemapChanges

Tile asset m_ColliderType 메타데이터 = 충돌 의도 SOT.
- m_ColliderType: 0 (None) = 배경 (충돌 X · 통과)
- m_ColliderType: 2 (Sprite) = 발판/지형 (충돌 ON)
발판 의도 Tile은 m_ColliderType=Sprite 명시 필수.

후속 점검 권고: 모든 Tile asset의 m_ColliderType 일제 검토 (PD 디자인 의도 정합 검증).

PD Refresh+Play 시 Console [BT49-Background] restored=N + 나무 통과 시각 검증.
본 PM 직접 Editor.log read 의무 (PD 시각 검증 결과 보고 직후).
This commit is contained in:
깃 관리자 2026-05-07 21:47:56 +09:00
parent b84c236761
commit 9adfc64625
1 changed files with 33 additions and 1 deletions

View File

@ -102,13 +102,20 @@ namespace Platformer.Mechanics
{ {
var pos = new Vector3Int(x, y, 0); var pos = new Vector3Int(x, y, 0);
if (!levelTilemap.HasTile(pos)) continue; if (!levelTilemap.HasTile(pos)) continue;
// BT49 — Tile asset의 m_ColliderType=None = 배경 의도 (예: tree·cloud) = 자동 분류 제외
var tileAsset = levelTilemap.GetTile<UnityEngine.Tilemaps.Tile>(pos);
if (tileAsset != null && tileAsset.colliderType == UnityEngine.Tilemaps.Tile.ColliderType.None) 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);
if (!aboveThreshold && !isSmallAir) continue; if (!aboveThreshold && !isSmallAir) continue;
var tile = levelTilemap.GetTile(pos); var tile = levelTilemap.GetTile(pos);
// BT49 — Foreground 이동 시 Tile asset 원래 colliderType 존중 (None=배경, Sprite=발판)
var srcColliderType = (tileAsset != null) ? tileAsset.colliderType : UnityEngine.Tilemaps.Tile.ColliderType.Sprite;
fgTilemap.SetTile(pos, tile); fgTilemap.SetTile(pos, tile);
fgTilemap.SetColliderType(pos, UnityEngine.Tilemaps.Tile.ColliderType.Sprite); fgTilemap.SetColliderType(pos, srcColliderType);
levelTilemap.SetTile(pos, null); levelTilemap.SetTile(pos, null);
if (aboveThreshold) movedHigh++; if (aboveThreshold) movedHigh++;
else movedSmall++; else movedSmall++;
@ -121,6 +128,31 @@ namespace Platformer.Mechanics
} }
} }
// BT49 — Foreground Tilemap 자체에 이미 그려진 배경 Tile (예: tree·cloud — Tile asset colliderType=None) ColliderType=None 복원
// BT47이 SetColliderType(Sprite) 무차별 강제 → 배경 Tile도 발판처럼 충돌 → Tile asset metadata 존중으로 정정
if (fgTilemap != null && fgTc != null)
{
int restored = 0;
var fgBounds = fgTilemap.cellBounds;
for (int x = fgBounds.xMin; x <= fgBounds.xMax; x++)
{
for (int y = fgBounds.yMin; y <= fgBounds.yMax; y++)
{
var pos = new Vector3Int(x, y, 0);
if (!fgTilemap.HasTile(pos)) continue;
var fgTileAsset = fgTilemap.GetTile<UnityEngine.Tilemaps.Tile>(pos);
if (fgTileAsset == null) continue;
if (fgTileAsset.colliderType == UnityEngine.Tilemaps.Tile.ColliderType.None)
{
fgTilemap.SetColliderType(pos, UnityEngine.Tilemaps.Tile.ColliderType.None);
restored++;
}
}
}
if (restored > 0) fgTc.ProcessTilemapChanges();
Debug.Log($"[BT49-Background] Foreground tile colliderType=None restored: {restored} (배경 Tile 충돌 차단)");
}
Debug.Log($"[BT48-DropThrough] Layer16 applied={applied} levelKeptLayer0={levelKept} excluded={excluded} total={allColliders.Length}"); Debug.Log($"[BT48-DropThrough] Layer16 applied={applied} levelKeptLayer0={levelKept} excluded={excluded} total={allColliders.Length}");
Debug.Log($"[BT48-DropThrough] appliedSamples=[{string.Join(", ", appliedNames)}]"); Debug.Log($"[BT48-DropThrough] appliedSamples=[{string.Join(", ", appliedNames)}]");
} }