Unity
어린이들이 블록을 끌어다 놓는 것만으로 자동차의 주행 경로를 직접 프로그래밍하고, 신호등·구급차·보행자 같은 실제 도로 상황까지 판단하게 만들 수 있다면 어떨까요?
전*원··수정됨 2026.07.21

자동차가 어떤 센서로 세상을 인식하는지 부품 조립 미니게임으로 자연스럽게 이어진다면요. 이번 포스팅에서는 성남박물관 '내가 만드는 자율주행' 체험 콘텐츠를 타일 맵 기반 상태 머신과 드래그 앤 드롭 블록 코딩으로 구현한 기술적인 과정을 공유합니다.

1. 시스템 아키텍처 개요
본 프로젝트는 크게 세 가지 단계로 구성됩니다.
블록 코딩: 방향 명령어 블록(상·하·좌·우)을 드래그해 코드 스택에 쌓고, CarCodingFlowController가 명령어를 순차적으로 해석
주행 시뮬레이션: 8×13 타일 맵 위에서 자동차가 Lerp 이동·회전하며, 벽·중간체크포인트·도착점·상황 타일을 자동 판정
부품 조립: 별도 씬 MakeAssemble에서 ECU·라이다·카메라·레이더·초음파 등 6종 자율주행 부품을 드래그해 차량에 조립
이 모든 과정은 Title / CarCoding / MakeAssemble 세 개의 씬과 HUDState enum 기반 상태 머신(State Machine)으로 연결되어 있습니다.
2. 주요 기술적 구현
2.1 2D 타일 맵 기반 주행 판정 (CarCodingFlowController.cs)
자동차의 주행 결과는 int[8,13] 2D 배열로 정의된 타일 맵 위에서 판정됩니다. 각 타일은 고유한 의미를 가지며, CoOrderStart() 코루틴이 명령어 리스트를 순회하며 매 스텝마다 MapCarRotate()로 방향 전환 → MapCarMove()로 Lerp 이동 → 목적지 타일 값 검사의 3단계를 반복합니다. 이 구조 덕분에 맵을 수정하거나 새 상황 타일을 추가하는 일이 2D 배열과 switch 분기 수정만으로 가능해졌습니다.
```
0 : 벽 / 장애물 (충돌 → 실패)
1 : 일반 길
9 : MD (중간 체크포인트 - 1단계 성공 필수)
10 : ED (도착점)
3/4/5 : 신호등 / 구급차 / 보행자 상황 타일
```
2.2 드래그 앤 드롭 블록 코딩 (StickerDrag.cs + StickerAdjustPos)
블록 인터랙션은 Unity UI의 IPointerDownHandler / IDragHandler / IPointerUpHandler 인터페이스를 조합해 구현했습니다. OnPointerDown()에서 원본 블록isOrigin=true)을 터치하면 Instantiate로 복제본을 생성하고, 드래그 중에는 canvas.scaleFactor를 반영해 해상도가 바뀌어도 정확히 커서를 따라가도록 계산합니다. 손을 떼는 순간 CarCodingFlowController.StickerAdjustPos()가 최근접 스택 탐색 알고리즘으로 블록을 가장 가까운 코드 스택에 자동 스냅시켜, 아이들이 정확한 좌표에 드롭하지 않아도 의도대로 동작하도록 했습니다.
2.3 상황 인지형 2단계 미션 (Coding2Start)
1단계가 단순 경로 프로그래밍이라면, 2단계는 실제 도로에서 마주치는 세 가지 상황에 대한 정답 패턴 매칭 방식으로 구현되었습니다. Coding2Start()가 사용자가 쌓은 명령어 리스트를 기대 패턴과 문자열 배열 단위로 비교해, 맞으면 다음 상황으로 진행하고 틀리면 재도전을 유도합니다. Coding2Waiting() 코루틴은 다음 미션으로 넘어가는 사이에 구급차와 보행자 NPC를 Fade In 시켜, 정적인 타일 맵에 극적인 전환감을 더합니다.
| 상황 | 정답 패턴 |
| :---: | --- |
| 신호등 | ["Red", "Pause"] / ["Green", "Forward"] / ["Yellow", "Stop or go..."] |
| 구급차 | ["...", "Ambulance", "Out"] |
| 보행자 | ["...", "Person", "Pause"] |
3. 사용자 경험(UX) 최적화
1 스택 1 블록 규칙 : 같은 코드 스택에 두 번째 블록이 떨어지면 StickerAdjustPos()가 기존 블록을 자동 삭제해, 아이들이 실수로 덮어 놓아도 혼란 없이 가장 최근 선택이 반영되도록 했습니다.
충돌 피드백 이펙트 : 자동차가 벽 타일에 닿으면 별도 MapCarImpactObject가 표시되며 실패 화면이 5초 뒤 자동 복귀해, 실패 후에도 "왜 부딪혔는지" 관찰할 여유를 제공합니다.
무인 키오스크 복구 : CarCodingQuitButton이 30초 유휴 감지 시 자동으로 Title 화면으로 복귀하고, 7회 연속 탭 감지 시 운영자가 앱을 종료할 수 있도록 해 무인 전시 환경에서 안정적으로 동작합니다.
사운드 동기화 씬 전환 : StartButtonManager가 클릭음의 재생 길이를 미리 받아 WaitForSeconds(length - 1.5f)로 대기한 뒤 씬을 로드해, 사운드가 잘리지 않으면서도 과도한 지연 없이 자연스럽게 전환됩니다.
4. 마치며
이 프로젝트는 어린이에게 "코딩은 어렵다"가 아니라 "코딩은 레고 블록을 쌓는 것과 같다"는 메시지를 몸으로 전달하는 작업이었습니다. 2D 타일 맵 위의 Lerp 이동, 최근접 스냅 알고리즘, 패턴 매칭 기반 상황 판정까지 기술적으로도 흥미로운 요소가 많았지만, 아이들이 직접 코딩한 자동차가 도로 위를 달리며 신호등 앞에서 멈추는 장면을 눈앞에서 목격하게 한 점에서 큰 의미가 있었습니다.
향후에는 2단계의 하드코딩된 정답 패턴을 ScriptableObject 데이터 테이블로 분리하여 새로운 상황(자전거·공사 구간 등)을 코드 수정 없이 추가할 수 있도록 확장하고, 실패 시 어떤 명령어에서 경로가 꺾였는지 시각적 트레이스 오버레이를 제공해 학습 효과를 한층 강화할 예정입니다.
읽기 도구
약 6분 읽기
이 글이 도움이 되었나요?