diff --git a/Assets/_Game/Scripts/Player/PlayerCamera.cs b/Assets/_Game/Scripts/Player/PlayerCamera.cs index a06a3deb..fc025a3d 100644 --- a/Assets/_Game/Scripts/Player/PlayerCamera.cs +++ b/Assets/_Game/Scripts/Player/PlayerCamera.cs @@ -17,16 +17,22 @@ namespace Colosseum.Player [SerializeField] private float maxPitch = 60f; [Header("Collision")] - [SerializeField] private float collisionRadius = 0.2f; - [SerializeField] private LayerMask collisionMask = ~0; // 기본: 모든 레이어 + [SerializeField] private float collisionRadius = 0.3f; + [SerializeField] private LayerMask collisionMask; + [SerializeField] private float minDistance = 0.5f; [SerializeField] private float minHeightAboveGround = 0.3f; // 바닥 위 최소 카메라 높이 + [Header("Smooth Distance")] + [Min(0.01f)] [SerializeField] private float distanceSmoothTime = 0.15f; + private Transform target; private float yaw; private float pitch; private Camera cameraInstance; private InputSystem_Actions inputActions; private bool isSpectating = false; + private float currentDistance; + private float distanceSmoothVelocity; public Transform Target => target; public bool IsSpectating => isSpectating; @@ -56,6 +62,10 @@ namespace Colosseum.Player inputActions = actions; isSpectating = false; + // 충돌 마스크 기본값 설정 (Default, Enemy, Ground 레이어만) + if (collisionMask == 0) + collisionMask = LayerMask.GetMask("Default", "Enemy", "Ground"); + // 기존 메인 카메라 사용 또는 새로 생성 cameraInstance = Camera.main; Debug.Log($"[PlayerCamera] Initialize: target={playerTransform?.name}, Camera.main={cameraInstance?.name ?? "NULL"}"); @@ -73,6 +83,10 @@ namespace Colosseum.Player } pitch = 20f; + // 부드러운 거리 보간 상태 초기화 + currentDistance = distance; + distanceSmoothVelocity = 0f; + // 카메라 위치를 즉시 타겟 위치로 초기화 SnapToTarget(); } @@ -109,6 +123,10 @@ namespace Colosseum.Player { if (target == null || cameraInstance == null) return; + // 부드러운 거리 보간 상태 리셋 + currentDistance = distance; + distanceSmoothVelocity = 0f; + UpdateCameraPosition(); } @@ -162,12 +180,22 @@ namespace Colosseum.Player // pivot → desiredPos 방향으로 SphereCast해서 지형 충돌 감지 Vector3 dir = desiredPos - pivot; float maxDist = dir.magnitude; + float targetDistance = distance; if (Physics.SphereCast(pivot, collisionRadius, dir.normalized, out RaycastHit hit, maxDist, collisionMask, QueryTriggerInteraction.Ignore)) { - // 충돌 지점에서 collisionRadius만큼 pivot 쪽으로 당김 - desiredPos = hit.point + dir.normalized * collisionRadius; + // 충돌 지점에서 collisionRadius만큼 pivot 쪽으로 당긴 거리 + targetDistance = Mathf.Max(minDistance, hit.distance - collisionRadius); } + // 부드러운 거리 보간 + currentDistance = Mathf.SmoothDamp(currentDistance, targetDistance, ref distanceSmoothVelocity, distanceSmoothTime); + currentDistance = Mathf.Max(minDistance, currentDistance); + + // 보간된 거리로 최종 오프셋 재계산 + offset = rotation * new Vector3(0f, 0f, -currentDistance); + offset.y += height; + desiredPos = target.position + offset; + // 카메라 아래에 지면이 너무 가까우면 위로 밀어올려 바닥 아래면이 보이지 않게 함 if (Physics.Raycast(desiredPos, Vector3.down, out RaycastHit groundHit, minHeightAboveGround + 1f, collisionMask, QueryTriggerInteraction.Ignore)) {