0%

Unity

한 도시의 수십 년 발전사를 **단 하나의 키오스크 화면** 안에 어떻게 담아낼 수 있을까요?

전*원··수정됨 2026.07.21

한 도시의 수십 년 발전사를 **단 하나의 키오스크 화면** 안에 어떻게 담아낼 수 있을까요?

낙하하는 아이콘이 메인 화면을 살아 움직이게 하고, 클릭 한 번이면 3페이지 스와이프 슬라이드·오래된 뉴스 영상·연속 스와이프 갤러리까지 서로 다른 11가지 콘텐츠 유형이 자연스럽게 펼쳐진다면요. 이번 포스팅에서는 성남시의 역사를 인터랙티브 콘텐츠로 풀어낸 성남박물관 '발전 스토리'를 멀티 모드 콘텐츠 로더메인 루프 애니메이션으로 구축한 기술적인 과정을 공유합니다.

아키텍처_01_전체구조.png

1. 시스템 아키텍처 개요

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

메인 루프: Main 상태에서 CoMainUIDrop() 코루틴이 1초 간격으로 아이콘을 낙하시키고, 5초 뒤 페이드, 10초 뒤 리셋을 무한 반복하여 화면을 "살아 있는" 상태로 유지

콘텐츠 디스패치: 아이콘 클릭 시 SelectIcon(index)가 인덱스에 따라 이미지 / 비디오 / 3페이지 스와이프 세 가지 모드로 분기하여 해당 콘텐츠를 동적으로 로드

뷰어 계층: DragImage / DragPage 두 종류의 드래그 핸들러가 콘텐츠 개수(1/2/3장)에 맞춰 적절한 페이지 인디케이터와 함께 활성화

이 모든 과정은 Unity 2022.3.41f1의 단일 씬 구조에서 DevStoryFlowController 싱글톤이 HUDState enum(Main / Select / Info)으로 3가지 UI 상태를 전환하며 조율됩니다.

2. 주요 기술적 구현

2.1 인덱스 기반 멀티 모드 콘텐츠 디스패처 (DevStoryFlowController.SelectIcon)

11종의 콘텐츠를 단일 로더 함수로 처리하기 위해 SelectIcon(int index)를 인덱스 분기 방식으로 설계했습니다. 특정 인덱스는 비디오 플레이어를 기동해 오래된 뉴스 영상을 재생하고, 또 다른 인덱스는 3페이지 수평 스와이프 뷰를 활성화하며, 나머지는 icons[] 프리팹 배열에서 대응하는 콘텐츠 프리팹을 Instantiate 하는 방식입니다. 추가로 해당 콘텐츠의 이미지 장수(1/2/3장)에 따라 페이지 인디케이터 UI와 드래그 영역을 자동으로 재구성해, 한 함수가 서로 전혀 다른 세 가지 시각적 경험을 모두 책임지도록 했습니다.

2.2 코루틴 기반 무한 메인 루프 애니메이션 (CoMainUIDrop + UIDropEffect.cs)

메인 화면이 정적이면 관람객은 이 앱이 켜져 있는지조차 알기 어렵습니다. CoMainUIDrop()는 10초 주기의 낙하 → 페이드 → 리셋 사이클을 무한 반복하는 코루틴입니다. 첫 5초 동안 MainDropObjects[] 요소를 1초 간격으로 SetFalling() 호출하여 아이콘을 fallSpeed = 350f 로 순차 낙하시키고, 이어서 ChangeAlphaValue() 코루틴이 초당 0.3f 씩 알파를 감소시켜 부드럽게 사라지게 합니다. 10초 후 Reset()이 모든 아이콘을 원위치로 되돌리며, 상태가 Main에서 벗어나면 StopAllCoroutines()으로 즉시 정지해 불필요한 연산이 남지 않도록 설계했습니다.

2.3 적응형 스와이프 뷰어 (DragImage.cs + DragPage.cs)

콘텐츠마다 이미지 장수가 달라 스와이프 범위를 일률적으로 고정할 수 없습니다. DragImage는 이미지 2장일 땐 0 < x < MaxLen로 한쪽 방향 스와이프만 허용하고, 3장일 땐 abs(x) < MaxLen로 양방향을 허용하여 경계에서 바운스가 어색하지 않도록 합니다. 한편 3페이지 스와이프 전용 DragPagepageWidth = 1920f, dragThreshold = 200f로 "클릭 vs 스와이프"를 명확히 구분하며, 페이지 이동 후 ChangePaginationIndicaton()을 호출해 하단 인디케이터의 현재 페이지 표시까지 함께 갱신합니다.

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

숨쉬는 메인 화면 : 10초 주기 낙하·페이드 루프가 관람객을 자연스럽게 이끌면서도 반복에 지치지 않도록 완급을 조절해, 지나가는 관람객에게 "무언가 움직이고 있다"는 시각적 단서를 지속적으로 제공합니다.

상황별 인디케이터 자동 전환 : 콘텐츠 이미지 장수에 따라 InfoTwoIconTextures / InfoThreeIconTextures 페이지 인디케이터가 자동으로 전환되고, 1장짜리 콘텐츠에서는 인디케이터 자체를 숨겨 시각적 노이즈를 제거합니다.

드래그/클릭 인텐트 분리 : minDragDistance = 50f 로 "짧은 이동은 클릭"을, dragThreshold = 200f 로 "일정 거리 이상 드래그해야 페이지 전환"을 구분해, 관람객이 의도치 않게 페이지가 넘어가는 당혹스러운 경험을 방지합니다.

무인 환경 자동 복귀 : DevStoryQuitButton이 30초 유휴 시 Main 상태로 자동 복귀하여 다음 관람객이 항상 같은 시작 지점에서 체험을 시작할 수 있도록 하고, 관리자는 빠른 7회 연타로만 앱을 종료할 수 있어 오작동 위험을 최소화했습니다.

4. 마치며

이 프로젝트는 이질적인 콘텐츠 유형(이미지·영상·멀티 슬라이드)을 하나의 시각적 언어로 묶어내는 작업이었습니다. 단일 SelectIcon() 함수가 인덱스 기반으로 전혀 다른 UI를 생성하고, 10초 주기 메인 루프가 공간을 "살아 있게" 만들며, 적응형 스와이프가 콘텐츠에 따라 인터랙션을 달리 가져가는 구조는 기술적으로도 흥미로웠지만, 관람객에게는 "여기 들어오면 뭔가 계속 일어나고 있다"는 체감을 일관되게 전달했다는 점에서 큰 의미가 있었습니다.

향후에는 현재의 인덱스 기반 하드코딩 분기ScriptableObject 기반 콘텐츠 에셋으로 전환하여 새로운 콘텐츠를 추가할 때 코드 수정 없이 에셋만 추가하면 되도록 확장하고, 해상도 1920×1080에 맞춰진 하드코딩 수치들을 해상도 독립 스케일링 로직으로 개선하여 다양한 키오스크 환경에 대응할 예정입니다.

읽기 도구

6분 읽기

이 글이 도움이 되었나요?

다음으로 읽기