[Unity] 3D 프로젝트 기능 정리

Gee·2025년 3월 7일

플레이어 Move()

    // 플레이어 이동 처리
    void Move()
    {
        // 입력값을 기준으로 이동 방향 계산
        Vector3 dir = transform.forward * curMovementInput.y + transform.right * curMovementInput.x;
        dir *= moveSpeed;
        dir.y = _rigidbody.velocity.y;  // 기존 Y축 속도 유지 (중력 반영)
        _rigidbody.velocity = dir;      // Rigidbody의 속도 설정
    }
  • 현재 플레이어의 Move는 Vector2로 받고 있음.
  • Vector2에서는 (X: 좌우, Y: 앞뒤)
  • Vector3에서는 (X: 좌우, Y: 위아래, Z: 앞뒤)
  • Unity의 3D 공간에서 캐릭터가 이동하는 방향은 X, Z 평면이기 때문에
    • 앞뒤 이동(W, S) → Z축(transform.forward)
    • 좌우 이동(A, D) → X축(transform.right)
    • 즉, curMovementInput.y가 Z축 이동량을, curMovementInput.x가 X축 이동량을 담당하는 것
  • 그래서 curMovementInput.y를 transform.forward(Z축)과 곱한 것
  • 반대로, 만약 curMovementInput.x를 transform.forward와 곱하면 좌우로 움직이게 될 것
  • 추가로 transform.right * curMovementInput.x; 부분은 플레이어가 왼쪽으로 기동하게 되면 값이 음수가 되기 때문에 자동으로 왼쪽 이동이 처리된다.
  • 그래서 따로 left를 고려하지 않아도 되는 것

Math.Clamp

  • Mathf.Clamp는 값을 특정 범위 안으로 제한하는 함수
    // 카메라 회전 처리
    void CameraLook()
    {
        // 마우스 움직임을 반영해 X축(상하) 회전 값 변경
        camCurXrot += mouseDelta.y * lookSensitivity;
        
        // camCurXrot 값을 minXLook ~ maxXLook 범위로 제한
        camCurXrot = Mathf.Clamp(camCurXrot, minXLook, maxXLook);
        
        // // 카메라 컨테이너 회전 적용
        // cameraContainer.localEulerAngles = new Vector3(-camCurXrot, 0, 0);
        //
        // // Y축(좌우) 회전 적용
        // transform.localEulerAngles += new Vector3(0, mouseDelta.x * lookSensitivity, 0);
    }
  • camCurXrot 값이 minXLook과 maxXLook 사이에서만 움직이도록 막아주는 역할을 한다.
  • mouseDelta.y * lookSensitivity -> 마우스 이동량을 회전 값에 반영
  • Mathf.Clamp(camCurXrot, minXLook, maxXLook);
    -> camCurXrot가 최솟값(minXLook)과 최댓값(maxXLook) 사이로 제한됨

왜 필요한가?

  1. 카메라가 360도 돌아가는 걸 방지

    • 마우스를 위로 계속 움직이면 고개가 90도 이상 꺾이는 걸 막아야 함
    • 아래로 계속 움직이면 뒤로 넘어가버리는 걸 막아야 함
    • Mathf.Clamp를 쓰면 일정 각도 이상 더 이상 회전하지 않도록 제한 가능
  2. 자연스러운 시점 제한

    • 예를 들어 minXLook = -85, maxXLook = 85이면:
    • 위로 볼 수 있는 최대 각도: 85도
    • 아래로 볼 수 있는 최대 각도: -85도
    • 이 범위를 넘어서면 값이 고정되므로, 화면이 어색하게 뒤집히는 걸 방지할 수 있음
  • 그래서 Mathf.Clamp를 쓰면 카메라가 일정 범위를 넘어가지 않도록 제한할 수 있고, 1인칭(FPS) 게임에서 고개가 180도 넘어가거나 화면이 뒤집히는 현상을 막아줄 수 있다.

Mathf.Min() & Mathf.Max()

Mathf.Min(a, b)

  • a와 b 중 더 작은 값 반환
    // 상태 값을 추가하는 함수 (체력 회복 등)
    public void Add(float value)
    {
        curValue = Mathf.Min(curValue + value, maxValue);   // curValue에 값을 더하지만, maxValue를 초과하지 않도록 제한
    }
  • 최대 값을 초과하는 걸 방지하기 위해 사용함
  • curValue = 90, value = 20, maxValue = 100일 때 90 + 20 = 110이 되지만, Mathf.Min(110, 100)이므로 curValue = 100 (최대 값 유지)

Mathf.Max(a, b)

  • a와 b 중 더 큰 값 반환
    // 상태 값을 감소시키는 함수 (데미지, 배고픔 감소 등)
    public void Subtrack(float value)
    {
        curValue = Mathf.Max(curValue - value, 0);  // curValue에서 값을 빼지만, 0 미만으로 내려가지 않도록 제한
    }
  • 최소 값이 0 이하로 내려가지 않도록 방지하기
  • curValue = 10, value = 20이면 10 - 20 = -10이지만, Mathf.Max(-10, 0)이므로 curValue = 0 (0 이하로 내려가지 않음)

localEulerAngles

  • localEulerAngles는 오브젝트의 로컬 공간에서의 회전 값을 나타내는 (X, Y, Z) 오일러 각도
  • 즉 부모 오브젝트 기준으로 회전값이 적용됨
    // 카메라 회전 처리
    void CameraLook()
    {
        // // 마우스 움직임을 반영해 X축(상하) 회전 값 변경
        // camCurXrot += mouseDelta.y * lookSensitivity;
        //
        // // camCurXrot 값을 minXLook ~ maxXLook 범위로 제한
        // camCurXrot = Mathf.Clamp(camCurXrot, minXLook, maxXLook);
        
        // 카메라 컨테이너 회전 적용
        cameraContainer.localEulerAngles = new Vector3(-camCurXrot, 0, 0);
        
        // Y축(좌우) 회전 적용
        transform.localEulerAngles += new Vector3(0, mouseDelta.x * lookSensitivity, 0);
    }
  • cameraContainer.localEulerAngles
    • cameraContainer는 카메라를 담고 있는 빈 오브젝트.
    • 마우스 이동(mouseDelta.y)을 X축 회전으로 변환해서 적용
    • camCurXrot를 사용하는 이유는 마우스를 위로 움직이면 시선이 위로 가도록 조정
    • -camCurXrot에 -를 붙인 이유
      • mouseDelta의 y값은 마우스를 아래로 드래그하면 마이너스가 됨.
      • 근데 플레이어 Rotation은 아래가 +, 위가 -로 적용됨.
      • 즉 마우스를 실제로 동작하는 것과 보여지는 것의 값이 반대임. 그래서 -를 붙여 부호를 바꿔주는 것
  • transform.localEulerAngles
    • 플레이어 본체를 좌우 회전.
    • transform.localEulerAngles는 플레이어의 회전 값
    • 마우스를 좌우로 움직이면 Y축 회전이 변경됨

왜 필요한가?

  1. 부모-자식 관계를 활용하기 위해

    • 카메라가 cameraContainer라는 부모 오브젝트 안에 들어 있음
    • 플레이어는 좌우(Y축)로만 회전, 카메라는 상하(X축)으로만 회전
    • 이렇게 분리하면 움직임이 자연스러워짐
  2. 직접 회전 값을 설정하려면 오일러 각이 필요

    • transform.rotation은 Quaternion 타입이라 직접 설정하기 어려움
    • localEulerAngles는 (X, Y, Z) 형태라 직관적으로 회전 설정 가능
  • localEulerAngles는 부모 오브젝트 기준의 (X, Y, Z) 회전 값이고, 카메라(상하)와 플레이어(좌우) 회전을 분리해서 처리할 때 유용하다.
  • Quaternion보다 다루기 쉬워서 직접 회전 값을 설정할 때 자주 사용됨
profile
...

0개의 댓글