0%

Unity

숫자 버튼 하나를 누를 때마다 자동차가 도로를 달리고, 로봇 팔이 흔들리며, 인체 그래프가 춤추듯 차오른다면 어떨까요?

전*원··수정됨 2026.07.21

숫자 버튼 하나를 누를 때마다 자동차가 도로를 달리고, 로봇 팔이 흔들리며, 인체 그래프가 춤추듯 차오른다면 어떨까요?

"공학적 사고"라는 추상 개념을 10가지 서로 다른 시각적 경험으로 풀어내되, 코드 베이스는 하나의 인터페이스 기반 액션 시스템으로 우아하게 통합할 수 있다면요. 이번 포스팅에서는 성남박물관 '공학자의 생각상자' 체험 콘텐츠를 인터페이스(Interface)와 싱글톤(Singleton) 패턴으로 확장 가능하게 설계한 기술적인 구현 과정을 공유합니다.

아키텍처_01_전체구조.png

1. 시스템 아키텍처 개요

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

입력 관리: 숫자 버튼(2, 3, 4, 6, 10) 클릭을 ButtonActionManager가 수신하여 AudioManager로 클릭음 재생 후 대응 애니메이션을 활성화

액션 디스패치: ActionManager가 자식 계층의 모든 ActionScriptInterface 구현체를 수집해 StartAction()을 일괄 호출

애니메이션 실행: 10여 종의 액션 스크립트가 각자의 타이밍·속도·진폭으로 Sin·Lerp·PingPong 기반 움직임을 재생

이 모든 과정은 Unity 2023.2.20f1의 단일 씬 구조에서 ActionManagerButtonActionManagerAudioManager 세 개의 싱글톤이 이벤트로 협업하는 방식으로 동작합니다.

2. 주요 기술적 구현

2.1 인터페이스 기반 액션 시스템 (ActionManager.cs)

다양한 애니메이션을 코드 수정 없이 확장할 수 있도록 모든 액션은 ActionScriptInterface 를 구현하도록 설계했습니다. 이 인터페이스는 StartAction() / StopAction() 두 메서드만 정의하며, ActionManagerGetComponentsInChildren<ActionScriptInterface>()로 자식 계층의 모든 구현체를 자동 수집합니다. 덕분에 새로운 효과를 추가할 때 매니저 로직을 건드릴 필요 없이 인터페이스만 구현한 스크립트를 해당 버튼의 자식 오브젝트에 부착하기만 하면 됩니다.

```csharp

public interface ActionScriptInterface {

void StartAction();

void StopAction();

}

```

2.2 10종의 수학적 움직임 라이브러리 (Actions/*.cs)

액션 라이브러리는 수학 함수를 시각적 움직임으로 변환하는 소규모 스크립트의 모음입니다. ArmWavingScriptMathf.Sin 기반으로 자연스러운 팔 흔들림을, ZoomInOutScriptMathf.PingPong으로 확대/축소 왕복을, BiggerAndRemoveScriptLerp 보간 후 페이드 아웃까지 이어지는 2단계 애니메이션을 제공합니다. 각 스크립트는 인스펙터 필드로 튜닝 파라미터를 노출해, 개발자가 아닌 디자이너도 값을 조정해가며 원하는 효과를 만들 수 있도록 했습니다.

ShowImage / ShowText: startTime ~ EndTime 구간 표시

EditAlphaValue: 페이드인·아웃 + IsLoop / IsReverse 옵션

ArmWaving: wavingAngle · wavingSpeed 로 Sin 파형 제어

FiledImage: fillAmount 증가 애니메이션 (그래프용)

2.3 웨이포인트 기반 자동차 시뮬레이션 (CarManager.cs + CarSpawner.cs + MoveToDestinationScript.cs)

"자동차" 버튼을 누르면 Black / Red / Blue 3종 차량이 각자 지정된 웨이포인트 경로를 따라 도로를 달립니다. CarSpawnerSpawnTime 간격으로 차량 프리팹을 생성해 CarPrefabs[3] 에서 선택 Instantiate하고, 생성된 차량에 부착된 MoveToDestinationScriptMoveTowards + RotateTowards 조합으로 웨이포인트를 순회합니다. Vector3.Distance < 0.5f 조건으로 도착을 판정해 다음 포인트로 자연스럽게 전환하며, 효과 종료 시 CarManager.DestoryAllCar()가 모든 차량을 일괄 제거해 씬을 깨끗한 상태로 되돌립니다.

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

버튼 스팸 차단 : 버튼을 누른 직후 interactable = false로 비활성화하고, BlockButtonTime 경과 후 자동 재활성화해 연속 클릭으로 인한 애니메이션 중첩을 원천 차단합니다.

주기적 사용자 안내 : PlayMainMetapo가 메인 나레이션을 루프 재생하며, 11초 주기로 "여기를 터치하세요" 손 이미지가 투명도 0.3 로 은은하게 깜빡여 관람객의 다음 행동을 자연스럽게 유도합니다.

자동 리소스 할당 오디오 : AudioManager.PlaySound(ESoundType)이 사용 가능한 AudioSource를 자동 탐색해 재생하고, 부족하면 동적으로 생성함으로써 여러 효과음이 겹치는 상황에서도 잘림 없이 부드럽게 출력됩니다.

파라미터화된 튜닝 : 깜빡임 주기·페이드 속도·자동차 Spawn 간격·팔 흔들림 각도까지 모든 수치가 인스펙터 필드로 노출되어, 현장 반응에 따라 빌드 없이 즉시 튜닝할 수 있도록 했습니다.

4. 마치며

이 프로젝트는 "공학적 사고"라는 추상적 전시 주제를 10가지 시각적 움직임으로 구체화하면서, 코드 레벨에서는 단 하나의 인터페이스로 우아하게 통합한 작업이었습니다. Sin·Lerp·PingPong 같은 기초 수학 함수를 조합한 마이크로 애니메이션 라이브러리는 기술적으로도 흥미로웠지만, 관람객이 "버튼 하나 눌렀는데 이렇게 다채로운 장면이 펼쳐진다"고 느끼게 한 점에서 큰 의미가 있었습니다.

향후에는 현재의 고정된 5개 숫자 버튼 구조를 데이터 기반 동적 버튼 시스템으로 확장해 전시 리뉴얼 시 코드 수정 없이 새 주제를 추가할 수 있도록 하고, 각 액션의 파라미터를 ScriptableObject 프리셋으로 저장해 테마별 애니메이션 묶음을 한 번에 전환할 수 있도록 개선할 예정입니다.

읽기 도구

6분 읽기

이 글이 도움이 되었나요?

다음으로 읽기