Unity 2D Camera 크기 이론 + Cinemachine 지터링 수정

농담고미고미·2024년 8월 17일

Unity 개발 일지

목록 보기
22/26

이번에는 이론적인 얘기를 해보자... 참고로 유니티 2D 게임 개발 책을 클론코딩 중입니다.

유니티 2D 프로젝트는 모두 직교 투영 카메라를 사용한다. 직교 투영 카메라는 가까운 오브젝트와 멀리 있는 오브젝트를 같은 크기로 렌더링한다.

직교 투영 카메라에는 화면 높이의 절반을 채울 수 있는 "월드 단위"의 개수를 나타내는 "크기"라는 속성이 있다. 월드 단위는 유니티에서 설정한 PPU(Pixels Per Unit), 즉 단위당 픽셀에 따라 정해진다. 이름에서 알 수 있듯이 단위당 픽셀은 유니티 엔진이 하나의 월드 단위 안에 그려야할 픽셀의 수를 나타낸다.

카메라의 크기를 구하는 공식 :

(수직 해상도 / PPU) * 0.5 = 카메라 크기

예제를 봅시다. 해상도가 960*640이라면 화면의 높이는 640 픽셀이다. 계산하기 쉽게 PPU를 64로 잡는다면, 640 % 64 = 10. 즉 월드 단위 10개를 차곡차곡 쌓으면 화면의 높이와 같고 월드 단위 5개를 쌓으면 화면 높이의 반과 같다는 뜻이다. 따라서 카메라 크기는 5다.

보기 좋은 픽셀 아트 게임을 만드는 비결은 해상도에 따라 직교 카메라의 크기를 신경 써서 정한 뒤에 정해진 PPU에 잘 어울리는 아트 작업을 하는 것이다.

지금 만드는 게임에서 해상도는 1280 * 720 인데, 약간의 속임수를 써서 모든 아트를 살짝 확대하려 한다. 즉 PPU에 배율 인수 3을 곱하려 한다.

(720 / (32PPU 3)) 0.5 = 3.75

따라서 카메라 크기는 3.75로 설정한다.

* 시네머신의 지터링 현상을 고쳐보자

약간의 화면 떨림을 지터링이라 하는데, 특히 플레이어를 따라오던 가상 카메라가 천천히 멈출 때 두드러진다. 이런 지터링 효과가 생기는 원인은 지나치게 정밀한 카메라 좌표계 때문이다. 플레이어는 픽셀 단위로 움직이지만, 플레이어를 따라가는 카메라는 픽셀보다 작은 단위로 움직인다.

지터링을 없애려면 시네머신 가상 카메라의 최종 위치가 픽셀 단위로 맞아떨어져야 한다. 확장 컴포넌트의 스크립트를 작성해서, 시네머신 가상 카메라의 마지막 좌표를 가로채서 설정한 PPU에 맞게 반올림할거다.

using UnityEngine;
using Cinemachine;

public class RoundCameraPos : CinemachineExtension
{
    public float PixelsPerUnit = 32;

    protected override void PostPipelineStageCallback(CinemachineVirtualCameraBase vcam, CinemachineCore.Stage stage, ref CameraState state, float deltaTime)
    {
        if(stage == CinemachineCore.Stage.Body)
        {
            Vector3 pos = state.FinalPosition;

            Vector3 pos2 = new Vector3(Round(pos.x), Round(pos.y), pos.z);
            state.PositionCorrection += pos2 - pos;
        }
    }

    float Round(float x)
    {
        return Mathf.Round(x * PixelsPerUnit) / PixelsPerUnit;
    }
}

시네머신의 프로세싱 파이프라인과 연결한 컴포넌트는 CinemachineExtension을 상속한다.

protected override void PostPipelineStageCallback(CinemachineVirtualCameraBase vcam, CinemachineCore.Stage stage, ref CameraState state, float deltaTime)은 Cinemachine을 상속한 클래스라면 반드시 구현해야 하는 메서드로 제한자의 처리가 끝나고 시네머신이 호출하는 메서드다.

Vector3 pos로 가상 카메라의 최종 위치를 얻는다.
반올림 메서드를 호출해서 위치를 반올림하고, 새로운 벡터를 pos2에 담는다.

state.PositionCorrection : 원래 위치와 방금 반올림해서 계산한 위치의 차이를 가상 카메라의 위치에 반영한다.

부가설명...을 하자.

유니티에서 state.PositionCorrection에 대해 설명하자면, 이 개념은 물리적 시뮬레이션이나 애니메이션 시스템에서 객체의 위치를 조정하거나 보정하는 데 사용되는 값입니다. 이 값은 일반적으로 특정 객체가 의도된 위치에서 벗어나거나, 원하는 결과를 얻기 위해 미세 조정이 필요할 때 사용됩니다.

주요 개념
Position Correction (위치 보정):
PositionCorrection 값은 객체의 현재 위치에 더해져서 새로운 위치를 결정합니다. 이는 객체가 예상 위치에서 벗어났을 때 그 차이를 보정하기 위해 사용됩니다. 예를 들어, 충돌이나 기타 외부 요인으로 인해 객체의 위치가 틀어졌을 때, 이를 바로잡기 위해 보정 값을 더할 수 있습니다.

Feedback (피드백 없음):
중요한 점은, 이 보정 값이 다음 프레임을 계산할 때 시스템에 다시 입력되지 않는다는 것입니다. 즉, 이 값은 한 번 사용되고 나면 그 값이 다음 계산에 영향을 미치지 않습니다. 이것은 PositionCorrection이 현재 프레임에서만 영향을 주고, 다음 프레임의 계산에는 포함되지 않음을 의미합니다.

profile
농담곰을 좋아해요 말랑곰탱이

0개의 댓글