diff --git a/Assets/Editor/PatrolPathEditor.cs b/Assets/Editor/PatrolPathEditor.cs deleted file mode 100644 index 9006e98..0000000 --- a/Assets/Editor/PatrolPathEditor.cs +++ /dev/null @@ -1,40 +0,0 @@ -using System.Collections; -using System.Collections.Generic; -using Platformer.Mechanics; -using UnityEditor; -using UnityEngine; -namespace Platformer -{ - [CustomEditor(typeof(PatrolPath))] - public class PatrolPathGizmo : Editor - { - public void OnSceneGUI() - { - var path = target as PatrolPath; - using (var cc = new EditorGUI.ChangeCheckScope()) - { - var sp = path.transform.InverseTransformPoint(Handles.PositionHandle(path.transform.TransformPoint(path.startPosition), path.transform.rotation)); - var ep = path.transform.InverseTransformPoint(Handles.PositionHandle(path.transform.TransformPoint(path.endPosition), path.transform.rotation)); - if (cc.changed) - { - sp.y = 0; - ep.y = 0; - path.startPosition = sp; - path.endPosition = ep; - } - } - Handles.Label(path.transform.position, (path.startPosition - path.endPosition).magnitude.ToString()); - } - - [DrawGizmo(GizmoType.Selected | GizmoType.NonSelected)] - static void OnDrawGizmo(PatrolPath path, GizmoType gizmoType) - { - var start = path.transform.TransformPoint(path.startPosition); - var end = path.transform.TransformPoint(path.endPosition); - Handles.color = Color.yellow; - Handles.DrawDottedLine(start, end, 5); - Handles.DrawSolidDisc(start, path.transform.forward, 0.1f); - Handles.DrawSolidDisc(end, path.transform.forward, 0.1f); - } - } -} diff --git a/Assets/Editor/PatrolPathEditor.cs.meta b/Assets/Editor/PatrolPathEditor.cs.meta deleted file mode 100644 index c9fcc3a..0000000 --- a/Assets/Editor/PatrolPathEditor.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 574b9f9d90f1a4e0180d882b20207004 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Scripts/Gameplay/PlayerEnemyCollision.cs b/Assets/Scripts/Gameplay/PlayerEnemyCollision.cs index 8a41556..d47f89b 100644 --- a/Assets/Scripts/Gameplay/PlayerEnemyCollision.cs +++ b/Assets/Scripts/Gameplay/PlayerEnemyCollision.cs @@ -41,7 +41,9 @@ namespace Platformer.Gameplay bool inAir = !player.IsGrounded; bool playerAbove = player.transform.position.y > enemy.transform.position.y; +#if UNITY_EDITOR && ENEMY_DIAG_VERBOSE Debug.Log($"[PEC] inAir={inAir} above={playerAbove} delta={dyAtCollision:F2} pY={player.transform.position.y:F2} eY={enemy.transform.position.y:F2}"); +#endif if (inAir && playerAbove) { diff --git a/Assets/Scripts/Mechanics/EnemyController.cs b/Assets/Scripts/Mechanics/EnemyController.cs index 02dc5fb..42127a2 100644 --- a/Assets/Scripts/Mechanics/EnemyController.cs +++ b/Assets/Scripts/Mechanics/EnemyController.cs @@ -12,7 +12,6 @@ namespace Platformer.Mechanics [RequireComponent(typeof(AnimationController), typeof(Collider2D))] public class EnemyController : MonoBehaviour { - public PatrolPath path; // legacy 호환·자동 patrol 영역 도입 후 미사용 public AudioClip ouch; /// BT5-Dev #16 — Distance 기반 감지 영역 X 임계값 (전체 폭). 표준 platformer Enemy 옆 닿음 영역 0.6~0.8. @@ -48,7 +47,6 @@ namespace Platformer.Mechanics private float _maxLeftRange; // 시작 시 측정 — 좌측 안전 patrol 거리 private bool _isInitialized; // BT97: Start 측정 완료 영역 (Awake 이후 활성) - internal PatrolPath.Mover mover; // legacy 호환·미사용 internal AnimationController control; internal Collider2D _collider; internal AudioSource _audio; @@ -110,7 +108,9 @@ namespace Platformer.Mechanics _maxRightRange = MeasureSafeWalkDistance(1f); _maxLeftRange = MeasureSafeWalkDistance(-1f); +#if UNITY_EDITOR && ENEMY_DIAG_VERBOSE Debug.Log($"[Enemy@{name}] startX={_startX:F2} startY={_startY:F2} maxR={_maxRightRange:F2} maxL={_maxLeftRange:F2}"); +#endif SetNextPatrolTarget(); _isInitialized = true; } @@ -193,7 +193,9 @@ namespace Platformer.Mechanics } if (startTm != null) break; } +#if UNITY_EDITOR && ENEMY_DIAG_VERBOSE Debug.Log($"[Enemy@{name}] dir={dir} startY={transformY:F2} colliderFoot={colliderFootY:F2} spriteFoot={spriteFootY:F2} chosenFootY={chosenFootY:F2} startTm={(startTm!=null?startTm.name:"NULL")} startCell={startCell}"); +#endif if (startTm == null) return 0f; // 좌·우 연속 Tile 영역 끝 영역 검색 @@ -369,11 +371,13 @@ namespace Platformer.Mechanics _cachedPlayer = Object.FindFirstObjectByType(); } +#if UNITY_EDITOR && ENEMY_DIAG_VERBOSE if (Time.frameCount % 60 == 0) { int allCount = Object.FindObjectsByType(FindObjectsSortMode.None).Length; Debug.Log($"[BT17-Update@{name}] f={Time.frameCount} cached={(_cachedPlayer != null ? _cachedPlayer.name : "NULL")} pgoTag={(pgo != null ? pgo.name : "NULL")} allPCcount={allCount}"); } +#endif } // BT20 — IgnoreCollision 영역 Awake 시점 Player 발견 X 영역 fallback. Update 영역에서 발견 직후 1회 영역 호출. @@ -384,7 +388,9 @@ namespace Platformer.Mechanics { Physics2D.IgnoreCollision(_collider, pc, true); _ignoreCollisionApplied = true; +#if UNITY_EDITOR && ENEMY_DIAG_VERBOSE Debug.Log($"[BT20-Ignore@{name}] Player↔Enemy IgnoreCollision applied"); +#endif } } if (_cachedPlayer != null && _cachedPlayer.health != null && _cachedPlayer.health.IsAlive) @@ -400,7 +406,9 @@ namespace Platformer.Mechanics if (inRange != _diagWasIntersecting) { +#if UNITY_EDITOR && ENEMY_DIAG_VERBOSE Debug.Log($"[EnemyDiag@{name}] inRange={inRange} footHeadDelta={footHeadDelta:F2} VB={VisualBounds.size} PB={_cachedPlayer.Bounds.size}"); +#endif _diagWasIntersecting = inRange; } diff --git a/Assets/Scripts/Mechanics/GameOptimizer.cs b/Assets/Scripts/Mechanics/GameOptimizer.cs index a660b48..fcd4c28 100644 --- a/Assets/Scripts/Mechanics/GameOptimizer.cs +++ b/Assets/Scripts/Mechanics/GameOptimizer.cs @@ -149,7 +149,9 @@ namespace Platformer.Mechanics if (fgTc != null) fgTc.ProcessTilemapChanges(); var lvlTc = levelGo.GetComponent(); if (lvlTc != null) lvlTc.ProcessTilemapChanges(); +#if UNITY_EDITOR && ENEMY_DIAG_VERBOSE Debug.Log($"[GameOptimizer] AutoForeground moved={movedHigh + movedSmall} (high={movedHigh} small={movedSmall} threshold={airThresholdY:F2}) / Layer16 applied={applied} levelKept0={levelKept} excluded={excluded}"); +#endif } } diff --git a/Assets/Scripts/Mechanics/PatrolPath.Mover.cs b/Assets/Scripts/Mechanics/PatrolPath.Mover.cs deleted file mode 100644 index 95cf726..0000000 --- a/Assets/Scripts/Mechanics/PatrolPath.Mover.cs +++ /dev/null @@ -1,38 +0,0 @@ -using UnityEngine; - -namespace Platformer.Mechanics -{ - public partial class PatrolPath - { - /// - /// The Mover class oscillates between start and end points of a path at a defined speed. - /// - public class Mover - { - PatrolPath path; - float p = 0; - float duration; - float startTime; - - public Mover(PatrolPath path, float speed) - { - this.path = path; - this.duration = (path.endPosition - path.startPosition).magnitude / speed; - this.startTime = Time.time; - } - - /// - /// Get the position of the mover for the current frame. - /// - /// - public Vector2 Position - { - get - { - p = Mathf.InverseLerp(0, duration, Mathf.PingPong(Time.time - startTime, duration)); - return path.transform.TransformPoint(Vector2.Lerp(path.startPosition, path.endPosition, p)); - } - } - } - } -} \ No newline at end of file diff --git a/Assets/Scripts/Mechanics/PatrolPath.Mover.cs.meta b/Assets/Scripts/Mechanics/PatrolPath.Mover.cs.meta deleted file mode 100644 index 56c8d3a..0000000 --- a/Assets/Scripts/Mechanics/PatrolPath.Mover.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 91fcc8d06d79c4678aabe2abed234213 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Scripts/Mechanics/PatrolPath.cs b/Assets/Scripts/Mechanics/PatrolPath.cs deleted file mode 100644 index bf279f4..0000000 --- a/Assets/Scripts/Mechanics/PatrolPath.cs +++ /dev/null @@ -1,28 +0,0 @@ -using UnityEngine; - -namespace Platformer.Mechanics -{ - /// - /// This component is used to create a patrol path, two points which enemies will move between. - /// - public partial class PatrolPath : MonoBehaviour - { - /// - /// One end of the patrol path. - /// - public Vector2 startPosition, endPosition; - - /// - /// Create a Mover instance which is used to move an entity along the path at a certain speed. - /// - /// - /// - public Mover CreateMover(float speed = 1) => new Mover(this, speed); - - void Reset() - { - startPosition = Vector3.left; - endPosition = Vector3.right; - } - } -} \ No newline at end of file diff --git a/Assets/Scripts/Mechanics/PatrolPath.cs.meta b/Assets/Scripts/Mechanics/PatrolPath.cs.meta deleted file mode 100644 index a829321..0000000 --- a/Assets/Scripts/Mechanics/PatrolPath.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 83b023ebe508a49c880fc00552f0dfc1 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Scripts/Mechanics/PlatformDropThrough.cs b/Assets/Scripts/Mechanics/PlatformDropThrough.cs deleted file mode 100644 index b16df30..0000000 --- a/Assets/Scripts/Mechanics/PlatformDropThrough.cs +++ /dev/null @@ -1,97 +0,0 @@ -using UnityEngine; - -namespace Platformer.Mechanics -{ - /// - /// BT5-Dev #27 — PD 제안 Layer + Raycast 동적 충돌. - /// Layer 8(JumpThrough) 발판은 기본 통과(IgnoreLayerCollision). Player 하강 + 발 Raycast 시점만 IgnoreCollision(false)로 충돌 활성 → 착지. - /// 점프(상승) 시 IgnoreCollision(true) 복구 → 다시 통과. - /// PlayerController.Awake에서 자동 부착. - /// - [RequireComponent(typeof(Collider2D))] - public class PlatformDropThrough : MonoBehaviour - { - const int JUMP_THROUGH_LAYER = 8; - - [Tooltip("발 raycast 기본 거리. velocity 영역에 따라 동적 확대.")] - public float footRayDistance = 1.0f; - - Collider2D _self; - KinematicObject _ko; - Collider2D _activePlatform; - int _jumpThroughMask; - - void Awake() - { - _self = GetComponent(); - _ko = GetComponent(); - _jumpThroughMask = 1 << JUMP_THROUGH_LAYER; - Debug.Log($"[BT32-DropThrough] Awake — self={(_self != null ? "OK" : "NULL")} ko={(_ko != null ? "OK" : "NULL")} mask={_jumpThroughMask}"); - } - - void Start() - { - Debug.Log($"[BT32-DropThrough] Start called"); - if (_self == null) return; - Vector2 footPos = new Vector2(_self.bounds.center.x, _self.bounds.min.y + 0.02f); - // BT32 — 거리 무한대 = Player 시작 위치 영역 발판 영역 영역 식별 - RaycastHit2D startHit = Physics2D.Raycast(footPos, Vector2.down, Mathf.Infinity, _jumpThroughMask); - if (startHit.collider != null) - { - Physics2D.IgnoreCollision(_self, startHit.collider, false); - _activePlatform = startHit.collider; - Debug.Log($"[BT32-StartHit] dist={startHit.distance:F2} platform='{startHit.collider.gameObject.name}' layer={startHit.collider.gameObject.layer}"); - } - else - { - Debug.Log($"[BT32-StartHit] no Layer 8 platform below footPos={footPos} (mask={_jumpThroughMask})"); - // 마지막 수단 — 모든 Layer raycast해서 가장 가까운 영역 식별 - RaycastHit2D anyHit = Physics2D.Raycast(footPos, Vector2.down, Mathf.Infinity); - if (anyHit.collider != null) - Debug.Log($"[BT32-AnyHit] anyLayer dist={anyHit.distance:F2} platform='{anyHit.collider.gameObject.name}' layer={anyHit.collider.gameObject.layer}"); - else - Debug.Log($"[BT32-AnyHit] NOTHING below player"); - } - } - - void Update() - { - if (_self == null || _ko == null) return; - - // Player 발 위치 (collider 하단 중심) - Vector2 footPos = new Vector2(_self.bounds.center.x, _self.bounds.min.y + 0.02f); - - // velocity 기반 동적 거리 (빠른 하강 시 raycast miss 차단) - float dist = Mathf.Max(footRayDistance, Mathf.Abs(_ko.velocity.y) * Time.deltaTime + 0.1f); - RaycastHit2D hit = Physics2D.Raycast(footPos, Vector2.down, dist, _jumpThroughMask); - - bool falling = _ko.velocity.y <= 0.01f; // 하강 또는 정지 - bool rising = _ko.velocity.y > 0.5f; // 점프 상승 - - if (rising) - { - // BT5-Dev #33 — 활성 해제 = 점프(상승) 시점만. 발판 떠남(낙하)은 활성 유지 (Player 거리 영역 벗어나도 충돌 유지·복구) - if (_activePlatform != null) - { - Physics2D.IgnoreCollision(_self, _activePlatform, true); - _activePlatform = null; - } - } - else if (falling && hit.collider != null && hit.collider != _activePlatform) - { - // 하강 + 발판 raycast hit → 충돌 활성 (착지) - Physics2D.IgnoreCollision(_self, hit.collider, false); - _activePlatform = hit.collider; - } - // BT33 — falling + hit X 영역 활성 해제 영역 폐기 (raycast 거리 일시 벗어남 영역 통과 복구 차단) - } - - void OnDrawGizmosSelected() - { - if (_self == null) return; - Vector2 footPos = new Vector2(_self.bounds.center.x, _self.bounds.min.y + 0.02f); - Gizmos.color = Color.cyan; - Gizmos.DrawLine(footPos, footPos + Vector2.down * footRayDistance); - } - } -} diff --git a/Assets/Scripts/Mechanics/PlatformDropThrough.cs.meta b/Assets/Scripts/Mechanics/PlatformDropThrough.cs.meta deleted file mode 100644 index 8725e6b..0000000 --- a/Assets/Scripts/Mechanics/PlatformDropThrough.cs.meta +++ /dev/null @@ -1,2 +0,0 @@ -fileFormatVersion: 2 -guid: bc0df74503a03ee478bb504a5cd1b0c3 \ No newline at end of file diff --git a/Assets/Scripts/Mechanics/PlayerController.cs b/Assets/Scripts/Mechanics/PlayerController.cs index e9d8bd5..0308796 100644 --- a/Assets/Scripts/Mechanics/PlayerController.cs +++ b/Assets/Scripts/Mechanics/PlayerController.cs @@ -91,9 +91,6 @@ namespace Platformer.Mechanics // 동반 컴포넌트 자동 부착 (Inspector 부착 불요) if (GetComponent() == null) gameObject.AddComponent(); if (GetComponent() == null) gameObject.AddComponent(); - // 구 PlatformDropThrough 컴포넌트 자동 제거 (Drop-Through는 ContactFilter mask 동적 갱신으로 처리) - var oldDrop = GetComponent(); - if (oldDrop != null) Destroy(oldDrop); // 사망 시 입력 차단 / 부활 시 입력 복원 if (health != null)