
2D 도트 게임을 위한 완벽한 픽셀 퍼펙트 카메라 설정
도트 아트가 흔들리거나 흐려지는 원인을 해상도와 카메라 이동 단위에서 찾는다. Unity 2D 기준으로 기준 해상도, PPU, 정수 배율, 카메라 스냅을 연결해 안정적인 픽셀 퍼펙트 화면을 만드는 방법을 정리한다.
픽셀 퍼펙트가 필요한 이유
2D 도트 게임에서 픽셀 퍼펙트란 월드의 한 픽셀이 화면에서도 선명한 정수 픽셀 단위로 표현되는 상태를 말한다. 이 조건이 깨지면 캐릭터가 천천히 움직일 때 가장자리가 흔들리거나 타일 경계에 미세한 틈이 생기고 스프라이트가 흐려질 수 있다.
문제는 카메라만의 문제가 아니다. 스프라이트의 PPU(Pixels Per Unit), 기준 해상도, 게임 창 크기, 카메라 위치, 텍스처 필터 설정이 함께 맞아야 한다. 하나만 어긋나도 화면 품질이 불안정해진다.

먼저 정할 값: 기준 해상도와 PPU
가장 먼저 게임이 어떤 가상 해상도에서 그려질지 정한다. 예를 들어 가로 320, 세로 180을 기준 해상도로 선택하면 16:9 화면에서 2배, 3배, 4배처럼 정수 배율로 확대하기 좋다.
그다음 스프라이트의 PPU를 정한다. 원본 타일이 16×16픽셀이고 PPU가 16이면 타일 한 칸은 Unity 월드에서 1유닛이다. 32×32 타일을 PPU 16으로 가져오면 한 칸은 2유닛이 된다. 어느 값을 고르든 프로젝트 전체에서 일관성을 지키는 편이 중요하다.
카메라가 세로 방향으로 보여 주는 월드 높이는 다음과 같이 계산할 수 있다.
기준 해상도 320×180, PPU 16이라면 Orthographic Size는 다음 값이다.
이 값은 카메라가 세로로 11.25 월드 유닛을 보여 준다는 뜻이다. 16픽셀 타일과 PPU 16을 사용한다면 정확히 11.25칸이 보이므로 타일 한 칸을 화면에 정수 픽셀로 표현하는 것과는 별개로 디자인상 의도한 시야인지도 확인해야 한다.
권장 가져오기 설정
스프라이트 텍스처는 보통 다음 설정으로 시작한다.
- Texture Type:
Sprite (2D and UI) - Filter Mode:
Point (no filter) - Compression:
None - Generate Mip Maps: 끔
- Pixels Per Unit: 프로젝트에서 정한 값으로 통일
Point 필터는 이웃 픽셀을 섞지 않아 도트 가장자리를 또렷하게 만든다. 다만 비정수 배율 자체를 해결하지는 못한다. 확대 비율과 카메라 위치가 어긋난 상태라면 선명하지만 들쭉날쭉한 화면이 될 수 있다.
Unity Pixel Perfect Camera 설정
Unity의 2D Pixel Perfect 패키지를 설치한 뒤 메인 카메라에 Pixel Perfect Camera 컴포넌트를 추가한다. URP 프로젝트라면 2D Renderer를 사용하는지도 함께 확인한다.
대표적인 설정은 다음과 같다.
| 항목 | 예시 값 | 의미 |
|---|---|---|
| Assets Pixels Per Unit | 16 | 스프라이트 Import Settings의 PPU와 동일 |
| Reference Resolution | 320 × 180 | 게임이 기준으로 삼을 가상 해상도 |
| Crop Frame | 필요할 때 활성화 | 화면 비율 차이를 레터박스 또는 필러박스로 처리 |
| Upscale Render Texture | 필요할 때 활성화 | 낮은 기준 해상도로 렌더링한 뒤 확대 |
| Pixel Snapping | 타일 기반 게임에서 우선 검토 | 렌더링 위치를 픽셀 격자에 맞춤 |
Assets Pixels Per Unit과 텍스처 Import Settings의 PPU가 다르면 스프라이트 크기와 카메라 계산이 달라진다. 이 값은 반드시 맞춘다.
Crop Frame은 기준 해상도와 다른 화면 비율에서 화면을 잘라 내거나 검은 여백을 넣어 기준 구도를 보존한다. 반면 화면을 꽉 채우는 것을 우선하면 일부 해상도에서 비정수 확대가 발생할 수 있다. 도트 그래픽의 안정성이 중요하다면 구도 보존과 정수 배율을 우선하는 편이 안전하다.
flowchart TD
A[기준 해상도 결정] --> B[스프라이트 PPU 통일]
B --> C[Pixel Perfect Camera에 동일 PPU 입력]
C --> D[정수 배율이 가능한 창 크기 선택]
D --> E[카메라 이동을 픽셀 격자에 스냅]
E --> F[여러 화면 비율에서 흔들림 확인]
카메라 이동은 픽셀 격자에 맞춘다
픽셀 퍼펙트 카메라를 사용해도 카메라가 월드 좌표의 임의 위치에 멈추면 화면이 미세하게 흔들릴 수 있다. 특히 플레이어를 부드럽게 따라가는 카메라에서 자주 드러난다.
월드 좌표 한 유닛에 PPU개의 픽셀이 있다면 카메라의 위치도 다음 간격으로 반올림할 수 있다.
PPU가 16일 때 한 화면 픽셀에 해당하는 월드 간격은 다음과 같다.
아래 스크립트는 목표 위치를 먼저 계산한 후 카메라 좌표를 해당 간격으로 스냅한다. 카메라의 Z 값은 2D 기본 카메라 거리로 유지한다.
using UnityEngine;
public class PixelPerfectFollowCamera : MonoBehaviour
{
[SerializeField] private Transform target;
[SerializeField] private float pixelsPerUnit = 16f;
[SerializeField] private Vector2 offset;
private void LateUpdate()
{
if (target == null)
{
return;
}
Vector2 desired = (Vector2)target.position + offset;
float pixelUnit = 1f / pixelsPerUnit;
float snappedX = Mathf.Round(desired.x / pixelUnit) * pixelUnit;
float snappedY = Mathf.Round(desired.y / pixelUnit) * pixelUnit;
transform.position = new Vector3(snappedX, snappedY, transform.position.z);
}
}
이 방식은 카메라가 픽셀 단위로 이동하게 한다. 다만 플레이어 자체가 서브픽셀 위치에서 움직이고 카메라만 스냅하면 플레이어와 배경의 상대적인 흔들림이 남을 수 있다. 강한 픽셀 일관성이 필요하다면 플레이어, 이동 플랫폼, 카메라의 최종 렌더링 위치를 같은 규칙으로 정렬해야 한다.

부드러운 추적과 픽셀 스냅을 함께 쓸 때
Vector3.Lerp나 Cinemachine의 Damping으로 카메라를 부드럽게 만들면 계산 결과는 대부분 소수 좌표가 된다. 이 값을 그대로 렌더링하면 픽셀 퍼펙트가 깨진다. 해결책은 보간한 논리 위치와 실제 렌더링 위치를 분리하는 것이다.
using UnityEngine;
public class SmoothedPixelCamera : MonoBehaviour
{
[SerializeField] private Transform target;
[SerializeField] private float followSpeed = 8f;
[SerializeField] private float pixelsPerUnit = 16f;
private Vector3 logicalPosition;
private void Start()
{
logicalPosition = transform.position;
}
private void LateUpdate()
{
if (target == null)
{
return;
}
Vector3 targetPosition = new Vector3(
target.position.x,
target.position.y,
logicalPosition.z
);
logicalPosition = Vector3.Lerp(
logicalPosition,
targetPosition,
1f - Mathf.Exp(-followSpeed * Time.deltaTime)
);
float pixelUnit = 1f / pixelsPerUnit;
float x = Mathf.Round(logicalPosition.x / pixelUnit) * pixelUnit;
float y = Mathf.Round(logicalPosition.y / pixelUnit) * pixelUnit;
transform.position = new Vector3(x, y, logicalPosition.z);
}
}
이 경우 논리 위치는 부드럽게 이동하지만 화면에 반영되는 위치는 픽셀 격자에 맞는다. 화면상 이동이 계단처럼 느껴질 수 있는데 이는 낮은 기준 해상도에서 픽셀 정확성을 유지할 때 생기는 자연스러운 특성이다. 더 부드러운 움직임이 필요하다면 기준 해상도나 PPU를 높이는 선택지를 검토한다.
타일 틈과 경계선 문제 점검
타일 사이에 가는 선이 보인다면 카메라 외에도 스프라이트 아틀라스를 확인해야 한다. 아틀라스에서 인접한 이미지의 색이 샘플링되거나 텍스처 가장자리에 빈 픽셀이 포함되면 틈처럼 보일 수 있다.
다음 순서로 점검하면 원인을 좁히기 쉽다.
- 모든 도트 텍스처가
Point필터와 무압축 설정인지 확인한다. - 타일의 원본 픽셀 크기와 PPU가 의도한 월드 크기를 만드는지 확인한다.
- Tilemap과 개별 타일의 Transform Scale이
(1, 1, 1)인지 확인한다. - Sprite Atlas를 사용한다면 패딩과 Extrude 설정을 확인한다.
- Game 뷰를 기준 해상도의 정수 배율로 표시해 본다.
- 실제 빌드 창 크기와 다양한 화면 비율에서 테스트한다.
특히 Transform Scale로 크기를 조절하는 습관은 피하는 편이 좋다. 16픽셀 타일을 크게 쓰고 싶다면 스케일을 1.5로 바꾸기보다 PPU와 타일 크기, 카메라 기준 해상도를 함께 설계하는 편이 결과를 예측하기 쉽다.
마무리 체크리스트
픽셀 퍼펙트는 특정 컴포넌트 하나를 추가해서 끝나는 기능이 아니다. 기준 해상도와 PPU를 먼저 고정하고 텍스처 필터, 카메라 크기, 정수 배율, 이동 좌표를 같은 규칙으로 묶어야 한다.
- 기준 해상도와 목표 화면 비율을 정했다.
- 모든 도트 스프라이트의 PPU가 통일되어 있다.
- 텍스처가
Point필터와 적절한 압축 설정을 사용한다. - Pixel Perfect Camera의 PPU와 기준 해상도가 프로젝트 설정과 일치한다.
- 카메라와 중요한 이동 오브젝트의 최종 렌더링 위치가 픽셀 격자에 맞는다.
- 지원 해상도와 화면 비율에서 실제로 흔들림과 타일 틈을 확인했다.
이 기준을 갖추면 화면 해상도가 바뀌어도 도트의 경계와 움직임을 훨씬 안정적으로 유지할 수 있다.


