유니티

유니티 - Cinemachine을 이용한 Camera Shake

재밌는게임~ 2025. 4. 24. 19:03

기존 카메라 쉐이크는 메인 카메라에서 tranform을 움직여서 쉐이크를 하는 방식이였다.

이번엔 시네머신을 통해서 카메라에 쉐이크를 해보면서 더욱 간단하게 만들 수 있었다.

 

- 메인 카메라 쉐이크 - 

public class ShakeCamera : MonoBehaviour
{
    private bool _isShaking = false; // 쉐이킹 상태를 추적
    private float _shakeDuration; // 쉐이킹 지속 시간
    private float _shakeMagnitude; // 쉐이킹 강도
    private float _elapsedTime; // 경과 시간
    private Vector3 _originalPosition; // 원래 위치
    private float _strength;

    private bool _isSkillShaking = false;
    private void Update()
    {
        ShakeFunc(_strength);   
    }

   public void Shake(float duration, float magnitude, float strength)
    {
        if (_isShaking) // 현재 쉐이킹 중이 아니면 시작
            return;
            _isShaking = true;
            _shakeDuration = duration;
            _shakeMagnitude = magnitude;
            _elapsedTime = 0.0f; // 경과 시간 초기화
            _originalPosition = transform.localPosition; // 원래 위치 저장
            _strength = strength;
    }

 

   //코루틴으로 대체 가능

   public void ShakeFunc(float strength)
    {
        if (_isShaking)
            {
                if (_elapsedTime < _shakeDuration)
                {
                    // X와 Y축으로 무작위 흔들림 생성
                    float x = Random.Range(-strength, strength) * _shakeMagnitude;
                    float y = Random.Range(-strength, strength) * _shakeMagnitude;

                    // 카메라의 위치를 업데이트
                    transform.localPosition = _originalPosition + new Vector3(x, y, 0);

                    // 경과 시간 갱신
                    _elapsedTime += Time.unscaledDeltaTime;

                    if(!BattleManager.Instance.IsShake)
                        return;
                }
                else
                {
                    // 흔들림 종료 후 원래 위치로 복원
                    transform.localPosition = _originalPosition;
                    _isShaking = false; // 쉐이킹 종료
                }
            }
    }

}

 

- 시네 머신 카메라 쉐이크 - 

활성화 될 카메라에 NoiseSettings 을 만들어준다.

*NoiseSetting ScriptableObject에서 Noise될 Position과 Rotation을 셋팅해줘야한다.

 

public class CameraShake : MonoBehaviour
{
    private CinemachineBasicMultiChannelPerlin noise;
    private void Awake()
    {
        noise = GetComponent<CinemachineBasicMultiChannelPerlin>();
    }
    
    
    public void Shake(float intensity, float duration)
    {
        //중복 방지
        if (noise.AmplitudeGain != 0)
            return;
        
        //StartCoroutine(ShakeRoutine(intensity, duration));
        ShakeRoutineUniTask(intensity, duration);
    }

    /*private IEnumerator ShakeRoutine(float intensity, float duration)
    {
        noise.AmplitudeGain = intensity;
        yield return new WaitForSeconds(duration);
        noise.AmplitudeGain = 0;
    }*/

    private async void ShakeRoutineUniTask(float intensity, float duration)
    {
        noise.AmplitudeGain = intensity;
        await UniTask.Delay(TimeSpan.FromSeconds(duration));
        noise.AmplitudeGain = 0;
    }
}

 

이렇게 훨씬 코드가 간단해졌다.  

이제 호출을 통해서 Shake를 해주면 된다.

 

private void CameraShake(float intensity, float duration)
{
    //현재 활성화된 VirtualCamera 가져오기 (ICinemachineCamera 타입)
    ICinemachineCamera activeCam = _mainCamera.ActiveVirtualCamera;
    //VirtualCameraGameObject를 통해 GameObject 접근
    CinemachineCamera camObj = (activeCam as CinemachineVirtualCameraBase)?.GetComponent<CinemachineCamera>();
    
    CameraShake cameraShake = camObj?.GetComponent<CameraShake>();
    cameraShake?.Shake(intensity, duration); // 원하는 세기로 흔들기
}

 

 

-비교-

Main Camera - transform.position

장점:

  • 구현이 단순하고 직관적 (그냥 transform.position += Random.insideUnitCircle)
  • Cinemachine 안 써도 됨 (순수 카메라)

단점:

  • Cinemachine을 쓴다면 충돌 가능성 높음
    → Cinemachine은 매 프레임마다 카메라 위치를 덮어쓰기 때문에,
    transform.position을 건드려도 무효가 되거나 튕김 현상 발생
  • 타 시스템(Zoom, Follow 등)이랑 충돌할 수 있음
  • 흔들림이 자연스럽지 않을 수 있음 (Perlin Noise나 감쇠 같은 처리 직접 구현해야 함)

Cinemachine Noise (CinemachineBasicMultiChannelPerlin)

장점:

  • Cinemachine의 모든 기능과 충돌 없이 연동 가능
  • 진짜 "카메라 흔들림" 느낌이 남
    → Perlin Noise 기반이라 랜덤하지만 부드럽고 감쇠 효과도 좋음
  • Virtual Camera마다 따로 설정 가능 (연출 다르게 가능)

단점:

  • 셋업이 처음엔 약간 귀찮음 (Virtual Camera + Noise 셋업)
  • 코드 접근 시 캐스팅 필요 (앞에서 했던 VirtualCameraGameObject 방식 등)

 

즉 시네머신을 사용하는 프로젝트에서는 Noise를 사용하고 사용하지 않는 프로젝트에서는 원래대로 transform을 건드리면 될거같다.

728x90