0%

Unity

발판을 밟으면 시작되는 30초 점프 대결

전*원··수정됨 2026.07.22

발판을 밟으면 시작되는 30초 점프 대결

전시장 바닥의 센서 발판 위에 올라서 두 발로 바닥을 두드리기 시작하면, 화면 속 AI 캐릭터 '달그리'와의 30초 점프 대결이 자동으로 시작됩니다. 이번 포스팅에서는 '달그리와 함께 점프해봐요' 콘텐츠의 기술적인 구현 과정을 공유합니다.

아키텍처_01_전체구조.png

1. 시스템 아키텍처 개요

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

- 발판 감지: 물리 점프 발판의 센서 신호를 시리얼로 수신해 게임 시작과 매 점프를 트리거합니다.

- 점프 경쟁 루프: 관람객 캐릭터 '영희'와 AI 캐릭터 '달그리'가 30초 동안 점프 횟수를 겨루며, 결과 말풍선으로 지구와 달의 중력 차이를 설명합니다.

- 배경 연동: 이웃 포토 부스 콘텐츠에서 만들어진 캐릭터 이미지를 TCP 로 수신해 배경에 실시간으로 스폰하고 자유롭게 움직이게 합니다.

메인 플랫폼은 Unity 단일 씬이며, 두 대의 발판(Zone 1/2)이 같은 PC 에서 동시에 구동되는 구조입니다.

2. 주요 기술적 구현

### 2.1 시리얼 점프 발판 감지 SerialPortManager.cs)

점프 발판의 마이크로컨트롤러는 baud 9600, 8N1 구성으로 [0xFA][Data] 2바이트 패킷을 실시간 송신합니다. Data 바이트의 Bit 0 은 Zone 1 발판, Bit 1 은 Zone 2 발판의 점프 신호로 매핑되어, 하나의 채널로 두 대의 키오스크 입력을 동시에 수신할 수 있는 구조입니다.

시리얼 읽기는 ReadTimeout = 500ms 를 건 전용 백그라운드 스레드에서 수행하고, 수신된 패킷은 ConcurrentQueue 에 적재한 뒤 Unity 메인 스레드의 Update() 에서 ProcessQueue() 로 꺼내어 처리합니다. 대기(Waiting) 상태에서는 2초 홀드로 게임 시작을 확정하고, 플레이 중에는 매 패킷이 StartJump() 로 흘러 Score++ 를 누적하는 방식으로 두 상태의 입력 의미를 분리했습니다.

2.2 30초 점프 경쟁 루프 MainGameController_JumpWithDalgree_Zone_1.cs)

게임 플로우는 CoGameFlow() 코루틴이 Waiting → Intro1(3초) → Intro2(3초) → Countdown(3.8초) → Playing(30초) → GameOver(3초) → Result(3초) → Finish(3초) 의 상태 전이를 순차로 진행합니다. 각 구간의 말풍선과 애니메이션은 YoungHiController_JumpWithDalgree.csDalgreeController_JumpWithDalgree.cs 가 나눠 담당합니다.

관람객 캐릭터 영희는 센서 신호마다 RegisterJump()jumpHeight = 0.25f, jumpDuration = 0.25f 의 짧은 스쿼시 애니메이션을 재생하며 Score 프로퍼티를 올립니다. 상대 AI 달그리는 CoAutoJump() 에서 speed = 30f 로 상승·하강을 반복해 자동으로 점프하고, 결과 페이지에서는 지구 중력과 달 중력의 차이를 서로 다른 말풍선으로 읽어 주어 교육적 맥락을 마무리합니다.

- 게임 시간: 30초

- 센서 홀드 시간: 2초

- 영희 애니메이션: Anim_YoungHi / 달그리: Anim_Dal

2.3 TCP 이미지 수신과 배경 캐릭터 TCPManager_JumpWithDalgree.cs, CharacterSpawner.cs)

TCPManager_JumpWithDalgree.cs 는 TCP 리스너로 이웃 포토 부스 콘텐츠로부터 [targetIndex:int32 BE][length:int32 BE][PNG bytes] 프레임을 수신합니다. 길이 필드는 0~10MB 범위로 검증해 비정상 프레임을 방어하고, 수신 성공 시 CharacterSpawner.SpawnCharacter(targetIndex, texture) 를 호출해 해당 이미지를 즉시 배경 캐릭터로 띄웁니다.

targetIndex / 4 연산으로 액션 타입을 결정해 '위아래 이동', '좌우 이동', '자유 이동 + 회전', '정지' 네 가지 행동 패턴 중 하나를 선택하고, 스폰된 캐릭터에는 CharacterMovement_JumpWithDalgree.csmoveSpeed 50~100 px/s, rotationSpeed 20~50°/s 의 랜덤 값을 부여해 캔버스 90% 경계 안에서 자유롭게 튀어 다니도록 만들었습니다. 이 덕분에 관람객이 직접 만든 캐릭터가 점프 게임의 배경에 살아 움직이는 연출이 완성됩니다.

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

발로 뛰는 직관적 입력 : 버튼이나 컨트롤러 대신 물리 발판으로 입력을 받아, 어린 관람객이 "뛰는 대로 화면 속 캐릭터가 뛴다"는 인과를 몸으로 바로 이해할 수 있게 했습니다.

두 대가 나란히 동시 플레이 : 같은 씬 안에 Zone 1·Zone 2 두 개의 게임 상태를 병렬로 돌려, 친구나 형제자매가 옆 키오스크에서 동시에 점프 대결을 펼칠 수 있도록 했습니다.

결과에 담긴 과학 메시지 : 게임 종료 후 영희와 달그리가 각각 지구와 달의 중력을 이야기하는 말풍선을 띄워, 점프 대결이라는 재미 위에 자연스러운 교육 포인트를 얹었습니다.

옆 콘텐츠로 이어지는 배경 : 이웃 포토 부스에서 만든 캐릭터가 이 게임의 배경으로 살아 들어와 뛰어다니도록 연결해, 관람 동선이 한 콘텐츠에서 끝나지 않고 공간 전체로 확장되게 했습니다.

4. 마치며

기술적으로 이 프로젝트는 물리 점프 발판과 이웃 콘텐츠의 TCP 스트림이라는 두 가지 이질적인 입력을 하나의 Unity 씬에서 동시에 소화한 사례입니다. 시리얼 큐잉과 상태 머신 기반 코루틴 덕분에 30초 게임이 진행되는 동안에도 배경에는 다른 관람객의 캐릭터가 끊김 없이 스폰되고, 하나의 PC 에서 두 대의 키오스크가 독립적으로 플레이되는 구성을 유지할 수 있었습니다.

향후에는 Zone 1/2 동일 구조를 공통 베이스 클래스로 추상화해 설정값만 달리 하는 인스턴스 두 개로 통합할 계획입니다. 또한 시리얼 입력에 라이징 엣지 감지를 추가해 발판 신호 품질이 불안정한 환경에서도 중복 카운트 없이 점프가 정확히 집계되도록 개선하고, ServerInfo.txt 의 포트 값을 런타임에서 완전히 반영하도록 통신 초기화 로직을 정리해 현장에서 코드 수정 없이 포트를 조정할 수 있는 구조로 확장할 예정입니다.

읽기 도구

7분 읽기

이 글이 도움이 되었나요?

다음으로 읽기