fix: 3인칭 카메라 폐색 시 순간이동 및 충돌 레이어 과도 포함 문제 수정

- 카메라 충돌 시 SmoothDamp로 부드럽게 보간하도록 변경 (기존: 즉시 hit.point 이동)
- collisionMask 기본값을 Default/Enemy/Ground 레이어로 제한 (기존: 모든 레이어 포함)
- collisionRadius 0.2→0.3 증가로 보스 등 대형 오브젝트 탐지 개선
- minDistance 0.5 추가로 카메라가 플레이어 모델 안으로 파고드는 현상 방지
This commit is contained in:
2026-04-02 22:35:57 +09:00
parent 188b134062
commit 90e3d4ae74

View File

@@ -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))
{