Post List

[유니티 엔진] Unity 2D에서 카메라 흔들기 구현하기(Camera Shaking)

Unity 2D에서 카메라 흔들기 구현하기(Camera Shaking)


카메라 흔들기 효과는,

- 타격감 구현 ( FPS를 예로 들면 총의 반동 표현)
- 지진, 폭발 등 특수효과를 더 실감나게 
에 사용됩니다.

카메라 흔들기 스크립트의 개요는 다음과 같습니다.

- 게임오브젝트의 초기 position, rotation 저장하기
- position을 랜덤으로 받아서 게임오브젝트의 position에 저장하기
- rotation을 랜덤으로 받아서 게임오브젝트의 rotation에 저장하기
- 진동을 마친 후 초기 rotation, position으로 복귀

위 개요에서 2, 3번 과정을 한번 실행이 아닌, 원하는 시간만큼 진동을 지속해야 하므로
반복문을 사용합니다. 반복문의 조건은 한 변수에 현재 프레임의 시간을 더해주며(deltaTime), 원하는 시간만큼 실행되었는지 판단하는 것 입니다.

불규칙한 위치를 적용하기 위해서 

Random.insideUnitCircle 을 사용하였습니다.
이 get함수는 x, y 좌표계에서 반지름이 1 인 원 안의 지점을 반환합니다.
현재 Unity 2D를 사용하고 있으므로 위 처럼 하였고, 만약 3D환경에서 개발하려고 한다면
Random.insideUnitSphere를 사용하면 되겠습니다. 

불규칙한 회전을 적용하기 위해서

Mathf.PerlinNoise(Time.time * offset)을 사용하였습니다.
펄린노이즈 함수는 일정부분 연속된 난수를 반환합니다. 그 특성으로 구름이나 나무 등 랜덤하지만 규칙성 있어야 하는 난수에 적용합니다. seed 값을 Time으로 둔 경우 입니다.

응용 예시


이 코드는 전역변수에 public Transform shakeCamera 하였습니다.
이 스크립트를 진동효과를 구현하고싶은 오브젝트에 첨부한 후 shakeCamera에 그 오브젝트를 첨부하면 되겠습니다. 카메라 전체를 흔들고싶다면 카메라를, 상자를 흔들고 싶다면 상자 오브젝트에 첨부하면 됩니다.

소스코드 : 


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

public class ShakeCamera : MonoBehaviour {

    // 진동할 카메라의 transform
    public Transform shakeCamera;
    // 회전시킬 것인지를 판단할 변수
    public bool shakeRotate = false;
    // 초기 좌표와 회전값을 저장할 변수
    public Vector3 originPos;
    public Quaternion originRot;

 // Use this for initialization
 void Start () {
        // 초깃값 저장
        originPos = shakeCamera.localPosition;
        originRot = shakeCamera.localRotation;
 }

    public IEnumerator Shake(float duration = 0.05f, float magnitudePos = 0.03f, float magnitudeRot = 0.1f)
    {
        // 지나간 시간을 누적할 변수
        float passTime = 0.0f;
        // 진동시간동안 루프 돌림
        while(passTime < duration)
        {
            // 불규칙한 위치를 산출
            Vector3 shakePos = Random.insideUnitCircle ;
            // 카메라의 위치를 변경
            shakePos.z = originPos.z / magnitudePos;
            shakeCamera.localPosition = shakePos * magnitudePos;
            
            // 불규칙한 회전을 사용할 경우
            if (shakeRotate)
            {
                // 펄린노이즈함수로 불규칙한 회전값 생성
                Vector3 shakeRot = new Vector3(0,0, Mathf.PerlinNoise(Time.time * magnitudeRot, 0.0f));
                // 카메라 회전값 변경
                shakeCamera.localRotation = Quaternion.Euler(shakeRot);
            }

            // 진동시간 누적
            passTime += Time.deltaTime;
            yield return null;
        }
        // 진동 후 원상복구
        shakeCamera.localPosition = originPos;
        shakeCamera.localRotation = originRot;

    }

}

댓글