Unity
벽을 흐르는 마음의 조각들
전*원··수정됨 2026.07.21

관람객의 이야기가 세 면의 벽을 가로지르며 떠다니는 말풍선이 되고, 손을 뻗어 한 번 쓸어내리면 그 마음이 흔들리며 색을 바꿉니다. 이번 포스팅에서는 '마음 저장소' 콘텐츠의 기술적인 구현 과정을 공유합니다.

1. 시스템 아키텍처 개요
본 프로젝트는 크게 세 가지 단계로 구성됩니다.
- 메시지 수신: 별도 부스에서 녹음된 음성이 텍스트로 변환되어 UDP 로 들어오면 말풍선으로 스폰됩니다.
- 터치 감지: YDLIDAR G4 라이다 센서가 벽 앞 공간을 스캔하고, DBSCAN 클러스터링으로 관람객의 손 위치를 추출합니다.
- 3면 렌더링: 좌·중·우 세 개의 캔버스에 말풍선을 분산시켜 떠다니는 애니메이션과 터치 반응을 동시에 보여 줍니다.
메인 플랫폼은 Unity 이며, 라이다 드라이버는 별도 Python 프로세스로 분리해 시리얼 파싱과 화면 렌더링을 독립적으로 운영합니다.
2. 주요 기술적 구현
2.1 라이다 기반 터치 감지 LIDARManager.cs)
Python 드라이버가 baud 230400 으로 YDLIDAR G4 의 원시 패킷을 읽어 거리·각도 배열을 JSON 으로 만들어 UDP 로 쏘면, LIDARManager.cs 가 백그라운드 스레드로 수신하여 프레임당 최대 5개 터치 포인트를 뽑아냅니다. 극좌표 데이터는 먼저 DBSCAN(클러스터 반경 400mm, 최소 5 포인트)으로 노이즈를 걸러낸 뒤, 인스펙터에 저장된 4점 캘리브레이션 값으로 화면 좌표로 사영시킵니다.
네 모서리의 (각도, 거리) 값을 기준으로 이중선형 매핑을 수행하기 때문에, 센서 설치 위치가 바뀌어도 현장에서 네 점만 다시 찍으면 즉시 재보정됩니다. Python 측에서는 170°~190° 정면 20도 범위만 통과시키고 5° 빈 단위의 최대 거리 테이블로 벽 뒤 반사를 차단하여, Unity 에 올라오는 시점에는 이미 유효 포인트만 남도록 했습니다.
2.2 말풍선 생명주기와 복원 MainManager.cs)
수신된 텍스트는 SpawnObjects(text, prefabType) 를 통해 말풍선으로 스폰되며, 0.5 ~ 1.3 사이 랜덤 스케일이 적용되어 화면에 다양한 크기감을 만듭니다. 한 장면에 최대 30개까지만 유지하고, 초과 시 EnforceGlobalLimit() 이 FIFO 로 가장 오래된 말풍선을 제거해 화면이 포화되지 않도록 합니다.
스폰된 메시지는 SaveData.txt 에 파이프 구분자로 최대 10개까지 누적 저장됩니다. 앱 재시작 시 LoadCacheAndBootstrap() 이 이 캐시를 읽어 이전 세션의 말풍선을 즉시 복원해, 관람객 입장에서는 "어제 내가 남긴 마음"이 오늘도 벽을 떠다니는 경험이 이어집니다.
- 최대 말풍선 수: maxObjectsTotal = 30
- 캐시 용량: CacheCapacity = 10
- 스폰 시 초기화: 랜덤 시작 위치 + 랜덤 목적지 + 랜덤 스케일
2.3 3면 투사 렌더링 DisplayRouter.cs)
벽이 하나의 평면이 아닌 꺾인 세 면으로 투사되기 때문에, canvasRTs[] 에 좌·중·우 세 개의 RectTransform 을 연결하고 말풍선 스폰 시 무작위 캔버스와 무작위 내부 좌표를 고릅니다. 그중 flippedCanvasIndex = 2 로 지정된 우측 캔버스는 프로젝터 배치상 좌우가 뒤집혀 있기 때문에, MapAcrossVertical() 이 X 축을 반전시켜 출력합니다.
말풍선 자체의 움직임은 DriftingUI.cs 가 담당합니다. 화면 밖으로 자연스럽게 흘러나간 뒤 다시 반대편에서 들어오며, 라이다 터치가 들어오면 좌우 흔들림과 색 변화 애니메이션을 재생해 "손을 대니 반응한다"는 피드백을 돌려줍니다.
3. 사용자 경험(UX) 최적화
세 면을 넘나드는 흐름 : 좌·중·우 캔버스에 말풍선을 분산 배치해, 벽을 따라 걸어가며 시야에 새로운 메시지들이 계속 들어오도록 했습니다.
손으로 만지는 반응 : 버튼 대신 라이다 기반의 비접촉 터치로 말풍선을 흔들고 색을 바꿔, 전시 공간에서 자연스러운 '쓰다듬기' 제스처가 인터랙션이 되도록 했습니다.
세션을 잇는 기억 : 최대 10개의 말풍선을 캐시해 다음 날 재시작해도 동일한 마음들이 벽을 계속 흐르도록 해, 공간 자체가 시간에 걸쳐 성장하는 느낌을 줍니다.
포화되지 않는 화면 : 30개를 초과하면 가장 오래된 말풍선부터 사라지게 하여, 벽이 아무리 많은 메시지를 받아도 한 번에 눈에 담을 수 있는 밀도로 유지됩니다.
4. 마치며
기술적으로 이 프로젝트는 Python 라이다 드라이버와 Unity 렌더러를 UDP 로 느슨하게 연결해, 하드웨어 변경이 있어도 한쪽만 수정하면 되도록 설계한 사례입니다. DBSCAN + 4점 캘리브레이션이라는 비교적 단순한 조합으로도 전시 환경에서 쓸 만한 비접촉 터치를 만들어 냈고, FIFO 캐시와 3면 매핑이라는 간결한 규칙이 "떠다니는 마음"이라는 은유를 온전히 감당하게 됐습니다.
향후에는 라이다 드라이버의 포트·캘리브레이션 값을 런타임 설정 파일로 분리해 현장에서 엔지니어 없이도 재설정이 가능하도록 개선할 예정입니다. 또한 캐시 저장 위치를 빌드 내부가 아닌 persistentDataPath 로 이전해, 재빌드 없이도 장기 운영 중 저장된 마음들이 누적될 수 있도록 구조를 확장할 계획입니다.
읽기 도구
약 6분 읽기
이 글이 도움이 되었나요?