0%

Unity

한 컷 사진이 옆방의 주인공이 되는 순간

전*원··수정됨 2026.07.22

한 컷 사진이 옆방의 주인공이 되는 순간

4K 웹캠 앞에서 한 컷을 찍고 포즈와 색상을 고르고 나면, 내 얼굴이 옆 콘텐츠의 배경 속 캐릭터로 살아 들어가 뛰어다닙니다. 이번 포스팅에서는 '찰칵! 한 컷 추억 남기기' 콘텐츠의 기술적인 구현 과정을 공유합니다.

아키텍처_01_전체구조.png

1. 시스템 아키텍처 개요

본 프로젝트는 크게 세 가지 단계로 구성됩니다.

- 촬영: 4K 웹캠 영상에서 정사각형 얼굴을 크롭해 650×650 고정 해상도의 한 컷을 만듭니다.

- 선택: 포즈(액션)와 색상을 조합해 단일 정수 targetIndex 로 변환한 뒤 캐릭터 프리팹을 즉시 미리보기합니다.

- 송신: 완성된 이미지와 targetIndex 를 TCP 로 이웃 게임 콘텐츠에 전달해 배경 캐릭터로 등장시킵니다.

메인 플랫폼은 Unity 단일 씬이며, 이웃 점프 게임 콘텐츠와 같은 PC 또는 같은 로컬 네트워크에서 TCP 로 연결됩니다.

2. 주요 기술적 구현

2.1 4K 웹캠 촬영과 크롭 CameraManager_TravelToTheMoon.cs, GuidePanelManager_TravelToTheMoon.cs)

CameraManager_TravelToTheMoon.csWebCamTexture(devices[0].name, 3840, 2160, 30) 로 첫 웹캠을 4K 30fps 로 잡고, uvRect = new Rect(1, 0, -1, 1) 로 좌우를 반전시켜 관람객이 화면을 거울처럼 보도록 표시합니다.

실제 촬영은 GuidePanelManager_TravelToTheMoon.csCoShotAndFreeze() 코루틴이 수행합니다. 화면에 표시된 cameraDisplayRect.localScale 값을 그대로 크롭 비율로 사용해 중앙을 잘라내고, 가로·세로 중 짧은 쪽에 맞춰 정사각형을 만든 뒤 픽셀 단위 샘플링으로 650×650 으로 리사이즈하며 좌우 반전을 한 번 더 적용합니다. 카메라 줌(Inspector Scale)과 출력 해상도를 분리한 덕분에, 설치 현장에서 카메라 위치를 옮겨도 인스펙터 스케일만 조정하면 동일한 구도로 얼굴이 잡힙니다.

2.2 포즈·색상 선택과 단일 인덱스 매핑 SelectColorPaneManager_TravelToTheMoon.cs)

선택 UI 는 두 단계로 나뉩니다. Panel 2 에서 촬영된 얼굴 이미지가 각 포즈 버튼의 RawImage 에 프리뷰로 들어가 ActionIndex 를 고르게 하고, Panel 3 에서 선택된 포즈별 4가지 색상 변형 중 하나를 골라 ColorIndex 를 확정합니다.

두 값은 targetIndex = (ActionIndex × 4) + ColorIndex 라는 단순 공식으로 하나의 정수에 병합되어, GameResourceManager.prefabs[targetIndex] 가 즉시 해당 캐릭터 프리팹을 localScale = 0.5 로 미리보기 인스턴스 화합니다. 프리팹 내부 RawImage 에 lastCapturedTex 를 입혀 얼굴·포즈·색상이 결합된 상태를 관람객이 확정 전에 확인하도록 했습니다. 60초 내 무입력 시에는 기본 인덱스 0 으로 자동 진행되어 다음 관람객이 대기하지 않도록 설계했습니다.

2.3 TCP 송신과 재연결 루프 TCPManager_TravelToTheMoon.cs, EndPanel_TravelToTheMoon.cs)

최종 확인을 마치면 EndPanel_TravelToTheMoon.csCoPlayLogic()TCPManager_TravelToTheMoon.csSendImage(texture, targetIndex) 를 호출합니다. 텍스처는 PNG 로 인코딩된 뒤 [targetIndex:int32 BE][length:int32 BE][PNG bytes] 의 빅엔디언 프레임으로 포장되어 이웃 서버 콘텐츠에 전송됩니다.

서버 주소는 StreamingAssets/ServerInfo.txt 에서 로드되며, ConnectLoop() 비동기 Task 가 2초 간격으로 재연결을 시도해 이웃 콘텐츠가 잠시 재시작되어도 자동으로 복구되도록 했습니다. 프레임 전송이 끝나면 EndPanel 은 8초짜리 결과 페이지를 유지한 뒤 홈 화면으로 복귀하여, 관람객이 자신의 캐릭터가 옆 콘텐츠에 등장하는 장면을 현장에서 직접 확인할 수 있는 전환 시간을 확보했습니다.

3. 사용자 경험(UX) 최적화

4K 해상도의 여유로운 크롭 : 3840×2160 원본을 확보해 두고 인스펙터 스케일 값으로 크롭 영역을 조정하는 구조로, 현장 조명·키 높이가 달라져도 재촬영 없이 즉시 동일한 구도를 맞출 수 있습니다.

재촬영의 선택권 : 첫 촬영 직후 재촬영 / 확인 버튼을 함께 보여 주어, 얼굴이 잘 찍히지 않았을 때 부담 없이 다시 시도할 수 있도록 했습니다.

포즈와 색상의 분리 선택 : 한 화면에 모든 조합을 나열하지 않고 포즈 → 색상 두 단계로 분리해, 어린 관람객이 동시에 많은 선택지에 압도되지 않도록 설계했습니다.

옆 콘텐츠로 확장되는 결과 : 완성된 캐릭터가 즉시 옆 콘텐츠 배경에 등장해 뛰어다니도록 TCP 로 연결하여, 체험이 포토 부스에서 끝나지 않고 동선 전체로 이어지는 공간 경험을 만들었습니다.

4. 마치며

기술적으로 이 프로젝트는 단순한 포토 부스가 아니라, 촬영 → 이미지 처리 → TCP 송신의 전 과정을 하나의 Unity 프로젝트에서 엮어 옆 콘텐츠의 실시간 배경을 구성하는 파이프라인으로 설계되었습니다. targetIndex = Action × 4 + Color 라는 단일 정수 매핑 덕분에 통신 프로토콜이 단순해지고, 프리팹 배열만 확장하면 포즈나 색상 개수를 늘리는 것도 용이한 구조를 갖췄습니다.

향후에는 연속 촬영 중 축적되는 Texture2D 객체를 프레임 종료 시점에 명시적으로 해제하여 장기간 무인 운영에서도 GPU 메모리 점유가 안정화되도록 개선할 예정입니다. 또한 TCP 전송 실패 시 관람객에게 재전송 버튼과 상태 메시지를 보여 주는 피드백 UI 를 추가해, 네트워크 장애 상황에서도 체험의 마무리가 매끄럽게 느껴지도록 확장할 계획입니다.

읽기 도구

6분 읽기

이 글이 도움이 되었나요?

다음으로 읽기