[Skill] 카메라 흔들기



카메라의 위치 회전값을 바꿔 카메라가 흔들리는 효과를 연출해보자!

(1) 카메라가 흔들리는것을 확인하기 위해 화면에 출력되는 스프라이트 오브젝트 하나를 생성해준다.

(2) 카메라 흔들기를 제어하는 ShakeCamera 스크립트를 작성해준다(위치 제어).

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ShakeCamera : MonoBehaviour
{
    private float shakeTime;
    private float shakeIntensity;

    private void Update()
    {
        //키보드에 숫자 1키를 누르면
        if (Input.GetKeyDown("1"))
        {
            OnShakeCamera(0.1f, 1f);
        }
    }

    //  외부에서 카메라 흔들림을 조작할 때 호출하는 메소드
    //  ex) OnShakeCamera(1);       => 1초간 0.1의 세기로 흔들림
    //  ex) OnShakeCamera(0.5f,1);       => 0.5초간 1의 세기로 흔들림
    /// <param name="shakeTime">카메라 흔들림 지속 시간 (설정하지 않으면 디폴트 1)
    /// <param name=shakeIntensity">카메라 흔들림 세기 (값이 클수록 세게 흔들린다)(설정하지 않으면 디폴트 0.1)
    public void OnShakeCamera(float shakeTime=1.0f,float shakeIntensity = 0.1f)
    {
        this.shakeTime = shakeTime;
        this.shakeIntensity = shakeIntensity;

        //현재 코루틴이 실행중일 수도 있기 때문에 중복 실행하지 않기 위해 멈춘 후 실행한다.
        StopCoroutine("ShakeByPosition");
        StartCoroutine("ShakeByPosition");
    }

    // 카메라를 shakeTime동안 shakeIntensity의 세기로 흔드는 코루틴 함수
    private IEnumerator ShakeByPosition()
    {
        // 흔들리기 직전의 시작 위치 (흔들림 종료 후 돌아올 위치)
        Vector3 startPosition=transform.position;

        while (shakeTime>0.0f)
        {
            // 특정 축만 변경하길 원하면 아래 코드 이용 (이동하지 않을 축은 0 값 사용)
            // float x = Random.Range(-1f, 1f);
            // float y = Random.Range(-1f, 1f);
            // float z = Random.Range(-1f, 1f);
            // transform.position = startPosition + new Vector3(x, y, z) * shakeIntensity;

            // 초기 위치로부터 구 범위(Size 1) * shakeIntensity의 범위에서 카메라 위치 변동
            transform.position=startPosition+Random.insideUnitSphere*shakeIntensity;

            // 시간 감소
            shakeTime-=Time.deltaTime;

            yield return null;
        }

        transform.position=startPosition;
    }
}

Random.insideUnitSphere : 반지름 1 크기의 구 내부 중 임의의 x,y,z 위치 값 생성 (Vector3)

여기서 임의의 (x,y,z)*shakeIntensity를 해주는 이유는 흔들림세기에 따라 카메라 위치 변동 범위를 줄이거나 넓히기 위해서이다.

(3) MainCamera오브젝트에 위 코드를 컴포넌트로 추가해준다.

(4) 게임을 싱행해서 숫자 1을 누르면 카메라의 위치가 바뀌어 그림이 흔들리게 보인다.

(5) 위 코드는 카메라의 위치 제어만 하였는데 위 코드에 카메라의 회전을 제어하는 코드를 넣어준다.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ShakeCamera : MonoBehaviour
{
    private float shakeTime;
    private float shakeIntensity;

    private void Update()
    {
        //키보드에 숫자 1키를 누르면
        if (Input.GetKeyDown("1"))
        {
            OnShakeCamera(0.1f, 1f);
        }
    }

    //  외부에서 카메라 흔들림을 조작할 때 호출하는 메소드
    //  ex) OnShakeCamera(1);       => 1초간 0.1의 세기로 흔들림
    //  ex) OnShakeCamera(0.5f,1);       => 0.5초간 1의 세기로 흔들림
    /// <param name="shakeTime">카메라 흔들림 지속 시간 (설정하지 않으면 디폴트 1)
    /// <param name=shakeIntensity">카메라 흔들림 세기 (값이 클수록 세게 흔들린다)(설정하지 않으면 디폴트 0.1)
    public void OnShakeCamera(float shakeTime=1.0f,float shakeIntensity = 0.1f)
    {
        this.shakeTime = shakeTime;
        this.shakeIntensity = shakeIntensity;

        //현재 코루틴이 실행중일 수도 있기 때문에 중복 실행하지 않기 위해 멈춘 후 실행한다.
        StopCoroutine("ShakeByRotation");
        StartCoroutine("ShakeByRotation");
    }

    // 카메라를 shakeTime동안 shakeIntensity의 세기로 흔드는 코루틴 함수
    private IEnumerator ShakeByPosition()
    {
        // 흔들리기 직전의 시작 위치 (흔들림 종료 후 돌아올 위치)
        Vector3 startPosition=transform.position;

        while (shakeTime>0.0f)
        {
            // 특정 축만 변경하길 원하면 아래 코드 이용 (이동하지 않을 축은 0 값 사용)
            // float x = Random.Range(-1f, 1f);
            // float y = Random.Range(-1f, 1f);
            // float z = Random.Range(-1f, 1f);
            // transform.position = startPosition + new Vector3(x, y, z) * shakeIntensity;

            // 초기 위치로부터 구 범위(Size 1) * shakeIntensity의 범위에서 카메라 위치 변동
            transform.position=startPosition+Random.insideUnitSphere*shakeIntensity;

            // 시간 감소
            shakeTime-=Time.deltaTime;

            yield return null;
        }

        transform.position=startPosition;
    }

    private IEnumerator ShakeByRotation()
    {
        // 흔들리기 직전의 회전 값
        Vector3 startRotation = transform.eulerAngles;

        // 회전의 경우 shakeIntensity에 더 큰 값이 필요하기 때문에 변수로 만들었음
        // (클래스 멤버변수로 선언해 외부에서 조작가능)
        float power = 10f;

        while (shakeTime > 0.0f)
        {
            // 회전하길 원하는 축만 지정해서 사용 (회전하지 않을 축은 0으로 설정
            // (클래스 멤버변수로 선언해 외부에서 조작하면 더 좋다)
            float x = 0;//Random.Range(-1f,1f)
            float y = 0;//Random.Range(-1f,1f)
            float z = Random.Range(-1f, 1f);
            transform.rotation = Quaternion.Euler(startRotation + new Vector3(x, y, z) * shakeIntensity * power);

            // 시간 감소
            shakeTime-=Time.deltaTime;

            yield return null;
        }
        // 흔들리기 직전의 회전 값으로 설정
        transform.rotation=Quaternion.Euler(startRotation);
    }
}

(6) 게임을 실행하고 숫자1을 누르면 카메라의 회전값이 바뀌어 그림이 흔들리는 효과가 연출된다.

(7) 외부에서 카메라 흔들기를 호출할 때 화면 흔들기가 필요한 클래스마다 ShakeCamera클래스 객체를 만들지 않도록 싱글톤 패턴을 적용해보자.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ShakeCamera : MonoBehaviour
{
    private static ShakeCamera instance;
    public static ShakeCamera Instance => instance;

    private float shakeTime;
    private float shakeIntensity;

    public ShakeCamera()
    {
        instance = this;
    }

    //  외부에서 카메라 흔들림을 조작할 때 호출하는 메소드
    //  ex) OnShakeCamera(1);       => 1초간 0.1의 세기로 흔들림
    //  ex) OnShakeCamera(0.5f,1);       => 0.5초간 1의 세기로 흔들림
    /// <param name="shakeTime">카메라 흔들림 지속 시간 (설정하지 않으면 디폴트 1)
    /// <param name=shakeIntensity">카메라 흔들림 세기 (값이 클수록 세게 흔들린다)(설정하지 않으면 디폴트 0.1)
    public void OnShakeCamera(float shakeTime=1.0f,float shakeIntensity = 0.1f)
    {
        this.shakeTime = shakeTime;
        this.shakeIntensity = shakeIntensity;

        //현재 코루틴이 실행중일 수도 있기 때문에 중복 실행하지 않기 위해 멈춘 후 실행한다.
        StopCoroutine("ShakeByRotation");
        StartCoroutine("ShakeByRotation");
    }

    // 카메라를 shakeTime동안 shakeIntensity의 세기로 흔드는 코루틴 함수
    private IEnumerator ShakeByPosition()
    {
        // 흔들리기 직전의 시작 위치 (흔들림 종료 후 돌아올 위치)
        Vector3 startPosition=transform.position;

        while (shakeTime>0.0f)
        {
            // 특정 축만 변경하길 원하면 아래 코드 이용 (이동하지 않을 축은 0 값 사용)
            // float x = Random.Range(-1f, 1f);
            // float y = Random.Range(-1f, 1f);
            // float z = Random.Range(-1f, 1f);
            // transform.position = startPosition + new Vector3(x, y, z) * shakeIntensity;

            // 초기 위치로부터 구 범위(Size 1) * shakeIntensity의 범위에서 카메라 위치 변동
            transform.position=startPosition+Random.insideUnitSphere*shakeIntensity;

            // 시간 감소
            shakeTime-=Time.deltaTime;

            yield return null;
        }

        transform.position=startPosition;
    }

    private IEnumerator ShakeByRotation()
    {
        // 흔들리기 직전의 회전 값
        Vector3 startRotation = transform.eulerAngles;

        // 회전의 경우 shakeIntensity에 더 큰 값이 필요하기 때문에 변수로 만들었음
        // (클래스 멤버변수로 선언해 외부에서 조작가능)
        float power = 10f;

        while (shakeTime > 0.0f)
        {
            // 회전하길 원하는 축만 지정해서 사용 (회전하지 않을 축은 0으로 설정
            // (클래스 멤버변수로 선언해 외부에서 조작하면 더 좋다)
            float x = 0;//Random.Range(-1f,1f)
            float y = 0;//Random.Range(-1f,1f)
            float z = Random.Range(-1f, 1f);
            transform.rotation = Quaternion.Euler(startRotation + new Vector3(x, y, z) * shakeIntensity * power);

            // 시간 감소
            shakeTime-=Time.deltaTime;

            yield return null;
        }
        // 흔들리기 직전의 회전 값으로 설정
        transform.rotation=Quaternion.Euler(startRotation);
    }
}

ShakeCamera클래스 사용 예시

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class InpuTest : MonoBehaviour
{
    private void Update()
    {
        if (Input.GetKeyDown("1"))
        {
            ShakeCamera.Instance.OnShakeCamera(0.1f, 1f);
        }
    }
}

위와 같이 클래스명.인스터스으로 접근 가능하다.




© 2022. by KSC

Powered by sora