유니티

[유니티6] Cinemachine Camera(시네머신 카메라)

디버그러 2025. 3. 22. 19:21

 

1. Cinemachine 카메라 생성

 

먼저 Package Manager에서 Cinemachine 패키지를 설치한다.

 

 

 

설치가 완료되면 하이어라키 창에 Cinemachine 탭이 추가된다.

  1. Cinemachine 탭에서 Cinemachine Camera를 추가한다.
  2. 추가된 오브젝트에는 Cinemachine 관련 컴포넌트가 자동으로 부착된다.
  3. Target플레이어 오브젝트로 설정한다.
  4. Control 옵션을 변경하면서 원하는 카메라 컨트롤 방식을 찾는다. 
    •   설정에 따라 Cinemachine이 자동으로 컴포넌트를 추가한다.

 

Damping 값이 클수록 카메라가 부드럽게 움직이지만, 반응 속도가 느려지고 화면이 울렁거릴 수 있다.

0.2 정도로 설정하면 자연스러운 카메라 움직임을 유지할 수 있다.

 

Control을 설정했을 때, Cinemachine 카메라의 위치는 Transform이 아니라 Offset 값을 조정해야 한다.

 

 

 

플레이어가 벽에 닿을 때 카메라가 흔들리거나 바닥으로 떨어지는 현상이 발생할 수 있다.

이는 물리 엔진이 충돌 시 플레이어의 위치를 미세하게 변경하기 때문이다.

 

이 문제를 해결하려면 Rigidbody 컴포넌트에서 Constraints의 특정 항목을 잠금 설정해야 한다.

  • Y축 위치(Position Y) 잠금 → 플레이어가 튀어오르는 현상 방지
  • 모든 회전(Rotation X, Y, Z) 잠금 → 카메라 각도가 변하는 문제 해결

 

 

 

2. Position Composer 모드

 

횡스크롤 게임과 같이 빠른 움직임이 필요한 경우 일반적인 Follow 모드를 사용하면 카메라가 원활하게 따라오지 않을 수 있다.

이를 해결하기 위해 Rotation Control을 None으로 설정하고, Position Composer을 사용한다.

 

 

Position Composer

 

Position Composer은 카메라 회전 없이 위치만 조정하는 기능이다.

특정 캐릭터나 오브젝트를 화면 중심에 고정하는 대신, 원하는 스크린 공간 위치를 유지하도록 설정할 수 있다.

 

설정 항목 설명
Dead Zone 대상이 이 범위 내에 있을 때 카메라가 움직이지 않음
Hard Limits 대상이 이 범위를 벗어나지 못하도록 제한

 

Dead Zone을 설정하면, 캐릭터가 화면 중앙에서 살짝 움직여도 카메라가 바로 반응하지 않는다.

즉, 작은 움직임에는 반응하지 않고, 범위를 벗어날 때만 따라가는 방식이다.

 

Dead Zone을 너무 작게 설정하면, 캐릭터가 조금만 움직여도 카메라가 따라가면서 불안정한 느낌이 든다.

너무 크게 설정하면, 캐릭터가 멀리 가야 카메라가 반응하기 때문에 불편할 수 있다.

 

 

Hard Limits를 설정하면, 대상이 특정 영역을 벗어나지 못하게 강제할 수 있다.

 

Hard Limits을 너무 작게 설정하면 플레이어가 아주 좁은 범위 안에서만 이동할 수 있어 답답할 수 있다.

너무 넓게 설정하면, 사실상 제한이 없는 것과 다름없어 원하는 효과를 얻기 어렵다.

 

 

대략 이런식으로 설정하면 된다.

 

 

 

3. 카메라 연출

 

플레이어 속도 변화에 따라 카메라 효과를 추가하면 더욱 생동감 있는 플레이를 만들 수 있다.

  • 속도가 빨라질 때LensVertical FOV 값을 증가시켜 멀리까지 보이도록 설정
  • 속도가 느려질 때Vertical FOV 값을 감소시켜 가까운 곳까지만 보이도록 설정

 

이를 적용하기 위한 CameraController 스크립트다.

using System.Collections;
using Unity.Cinemachine;
using UnityEngine;

public class CameraController : MonoBehaviour
{
    [Header("References")]
    private CinemachineCamera _cinemachineCamera;

    [Header("Camera Settings")]
    [SerializeField] private float minFOV = 35f;
    [SerializeField] private float maxFOV = 85f;
    [SerializeField] private float zoomDuration = 1f;
    [SerializeField] private float zoomSpeedModifer = 5f;
    
    [Header("Debug")]
    private Coroutine currentFOVRoutine;
    private float targetFOV; // 최종 FOV 값

    private void Awake()
    {
        _cinemachineCamera = GetComponent<CinemachineCamera>();
        targetFOV = _cinemachineCamera.Lens.FieldOfView;
    }

    public void ChangeCameraFOV(float speedAmount)
    {
        // targetFOV 설정 및 제한
        targetFOV = Mathf.Clamp(targetFOV + (speedAmount * zoomSpeedModifer), minFOV, maxFOV);
        
        // 기존 코루틴이 실행중이면 중단 후 새로운 코루틴 실행
        if (currentFOVRoutine != null)
        {
            StopCoroutine(currentFOVRoutine);
        }

        currentFOVRoutine = StartCoroutine(ChangeFOVRoutine());
    }

    private IEnumerator ChangeFOVRoutine()
    {
        float startFOV = _cinemachineCamera.Lens.FieldOfView; // 현재 FOV 값 저장
        float elapsedTime = 0f; // 경과 시간 초기화

        while (elapsedTime < zoomDuration) // zoomDuration(1초) 동안 반복
        {
            float t = elapsedTime / zoomDuration;
            elapsedTime += Time.deltaTime;
			
            // Lerp를 사용해 startFOV에서 targetFOV까지 부드럽게 변화
            _cinemachineCamera.Lens.FieldOfView = Mathf.Lerp(startFOV, targetFOV, t);
            yield return null; // 프레임마다 자연스럽게 변화
        }

        _cinemachineCamera.Lens.FieldOfView = targetFOV; // 반복이 끝나면 targetFOV 값을 강제 설정 (오차 보정)
    }
}

 

  1. ChangeCameraFOV(float speedAmount) 함수 
    •   speedAmount * zoomSpeedModifer를 더하여 targetFOV를 설정
    •   Clamp를 사용해 minFOVmaxFOV 사이의 값으로 제한
    •   기존 코루틴이 실행 중이면 StopCoroutine()으로 중단 후 새로운 코루틴 실행
  2. ChangeFOVRoutine() 코루틴
    •   Lerp를 사용해 startFOV에서 targetFOV로 부드럽게 변화
    •   yield return null을 사용하여 프레임마다 자연스럽게 변화하도록 설정
    •   마지막에는 targetFOV 값을 강제 적용하여 오차 보정

이러한 방식으로 속도에 따른 카메라 연출을 부드럽게 조정할 수 있다.

 

 

 

4. 카메라 흔들림 효과

 

시네머신 카메라에서 Add Extension을 눌러 CinemachineImpulseListener를 추가한다.

자동으로 컴포넌트가 추가되며, 이를 사용하기 위해 Cinemachine Impulse Source를 수동으로 추가한다.

 

플레이 모드에서 Test with Force의 Invoke 버튼을 누르면 실제로 흔들림을 확인할 수 있다.

 

 

 

오브젝트가 특정 충돌에 반응해 흔들림을 발생시키려면 Cinemachine Collision Impulse Source를 추가해야 한다.

또한 시네머신 카메라에 Cinemachine Inpulse Listener를 추가하는 것도 잊으면 안된다.

 

 

 

  • Impulse Type: Uniform → 균일한 충격 효과 적용
  • Impulse Shape: Bump → 충격이 발생하는 형태를 결정
  • Default Velocity: X: 0.2, Y: -1, Z: 0.2 → 기본 충격 방향 설정

 

이제 이 설정을 활용하여 충돌 시 카메라 흔들림이 발생하도록 코드를 작성한다.

 

using Unity.Cinemachine;
using UnityEngine;

public class Rock : MonoBehaviour
{
    [Header("References")]
    private CinemachineCollisionImpulseSource _impulseSource;

    [Header("Settings")]
    [SerializeField] private float shakeModifer = 10f;

    private void Awake()
    {
        _impulseSource = GetComponent<CinemachineCollisionImpulseSource>();
    }

    private void OnCollisionEnter(Collision collision)
    {
        // 바위와 메인 카메라 사이의 거리 계산
        float distance = Vector3.Distance(transform.position, Camera.main.transform.position);

        // 거리에 따라 흔들림 강도 계산
        float shakeIntensity = (1f / distance) * shakeModifer;
        shakeIntensity = Mathf.Min(shakeIntensity, 1f);

        // 카메라 흔들림 발생
        _impulseSource.GenerateImpulse(shakeIntensity);
    }
}

 

이렇게 설정하면 바위가 충돌할 때 거리 기반으로 자연스러운 흔들림이 발생한다.