본문 바로가기

UI 애니메이션 구현

위젯 타임라인에 위치·크기·투명도 키를 배치하고 그래프에서 재생·정지·반복을 제어해 UI 전환을 만듭니다.

메뉴 버튼을 누르는 순간 설정 창이 화면에 툭 나타났다가, 닫기를 누르면 툭 사라집니다. 기능은 정확하지만 플레이어는 창이 어디서 왔는지, 버튼이 정말 눌렸는지를 한 박자 늦게 알아챕니다. 창이 아래에서 미끄러져 올라오거나 버튼이 눌린 순간 살짝 커졌다 돌아오면, 같은 기능이라도 무슨 일이 일어났는지가 훨씬 분명해집니다.

이 글에서는 위젯 블루프린트의 애니메이션 기능으로 UI 요소의 위치, 크기, 투명도를 시간에 따라 바꾸는 방법을 익힙니다. 애니메이션과 트랙을 만들고 키프레임으로 변화를 기록한 뒤, 그래프에서 재생과 정지를 제어하고, 재생이 끝난 시점을 정확히 아는 방법까지 다룹니다.


UI 애니메이션이 하는 일

UI 애니메이션은 위젯 블루프린트 안의 버튼, 텍스트, 이미지, 패널 같은 요소의 속성, 즉 위치, 크기, 회전, 투명도, 색상을 시간에 따라 바꾸는 것입니다.

애니메이션은 먼저 플레이어의 행동에 즉각적인 피드백을 줍니다. 버튼을 눌렀을 때 잠깐 커졌다 돌아오거나, 아이템을 얻었을 때 아이콘이 튀어 오르면 입력이 받아들여졌다는 것을 바로 알 수 있습니다. 새 패널이 서서히 나타나거나 중요한 메시지가 깜빡이면 플레이어의 시선이 그쪽으로 이끌려, 무엇이 중요한지도 전달됩니다. 또 갑작스럽게 나타나고 사라지는 UI는 플레이어를 혼란스럽게 할 수 있는데, 애니메이션은 이런 전환을 자연스럽게 이어 주어 사용자 경험과 게임의 완성도를 함께 높입니다.


애니메이션과 트랙 만들기

위젯 블루프린트의 애니메이션은 시간 축 위에 값을 기록하는 방식이라서, 시퀀서(Sequencer)의 타임라인과 비슷하게 다룹니다. 위젯 블루프린트 에디터의 디자이너 탭에서 애니메이션(Animations) 창을 열고 +Animation 버튼을 누른 뒤, 새 애니메이션의 이름을 정합니다(예: FadeInAnim, ButtonPulse).

새 애니메이션을 선택하면 타임라인이 나타납니다. 타임라인의 + Track 버튼을 눌러 애니메이션을 적용할 위젯(예: StartGameButton)을 고르면 그 위젯의 트랙이 추가됩니다. 여기서 헷갈리기 쉬운 점이 하나 있습니다. Is Variable은 그래프에서 그 위젯의 참조를 쓰기 위한 옵션이고, 애니메이션 트랙의 대상을 고르는 것과는 별개입니다.

위젯 트랙 오른쪽의 + 버튼을 누르면 애니메이션할 속성을 고를 수 있습니다. 자주 쓰는 속성은 세 가지입니다. Render Transform은 위치(Translation), 회전 각도(Angle), 크기(Scale), 기울기(Shear)처럼 위젯의 시각적 변형을 조절합니다. Color And Opacity는 위젯의 색상과 투명도(Alpha)를 조절하며 Text나 Image 위젯에 유용합니다. Render Opacity는 패널을 포함한 위젯 전체의 표시 불투명도를 조절합니다. 모든 속성이 트랙을 지원하지는 않으므로, 그 위젯에 제공되는 키프레임 가능한 속성 가운데서 고릅니다.


키프레임으로 변화 기록하기

키프레임(keyframe)은 특정 시각의 속성 값을 기록한 점이고, 두 키프레임 사이의 값은 엔진이 채웁니다. 버튼이 위에서 내려오는 움직임을 만든다고 해 봅시다. 먼저 타임라인 헤드를 0초에 두고, 고른 속성(예: Render Transform의 Translation)의 Y 값을 -100으로 정한 뒤 속성 옆의 키 추가 버튼을 눌러 현재 값을 키프레임으로 기록합니다. 다음으로 헤드를 1초로 옮기고 Y 값을 0으로 바꾼 뒤 다시 키를 추가합니다. 이제 0초부터 1초 동안 버튼이 위쪽 100만큼에서 제자리로 내려오는 애니메이션이 만들어집니다.

키를 하나씩 추가하는 대신 자동 키(Auto Key) 옵션을 켜 두면, 헤드를 옮긴 뒤 디테일 패널에서 값을 바꾸는 것만으로 키가 기록됩니다. 다 만든 애니메이션은 타임라인의 재생 버튼으로 미리 볼 수 있습니다.


그래프에서 재생하고 제어하기

애니메이션은 만들어 두기만 해서는 재생되지 않으므로 그래프에서 재생을 지시해야 합니다. 그래프 탭으로 이동하면 만든 애니메이션이 위젯 블루프린트의 변수로 들어 있으며, 애니메이션 목록에서 그래프로 끌어 놓으면 그 애니메이션의 Get 노드가 만들어집니다. 이 핀에서 끌어 다음 노드들을 연결해 재생을 제어합니다.

  • Play Animation: 애니메이션을 재생하는 기본 노드입니다. In Animation에 애니메이션을 연결하고, Start at Time으로 시작 위치를, Play Mode로 정방향(Forward)이나 역방향(Reverse)을, Playback Speed로 재생 속도(기본 1.0)를, Num Loops to Play로 반복 횟수(0이면 무한 반복)를 정합니다.
  • Play Animation Forward / Play Animation Reverse: 지금 재생 상태를 기준으로 정방향이나 역방향으로 재생합니다. 시작 위치를 직접 정하려면 Play Animation의 Start at Time을 씁니다.
  • Pause Animation: 애니메이션을 일시 정지합니다.
  • Stop Animation: 애니메이션을 완전히 멈춥니다.
  • Is Animation Playing: 애니메이션이 지금 재생 중인지 확인합니다.

재생이 끝난 시점 알기

Play Animation의 일반 실행 출력은 재생이 끝나기를 기다리는 핀이 아닙니다. 재생을 시작하라고 지시한 직후 곧바로 다음 노드로 넘어가므로, 이 출력 뒤에 "창 닫기"를 연결하면 닫는 애니메이션이 보이기도 전에 창이 사라집니다.

재생이 끝난 뒤에 할 일은 끝났다는 알림에 연결합니다. Bind to Animation Event 노드로 대상 애니메이션과 끝남(Finished) 이벤트를 지정해 커스텀 이벤트를 등록하거나, 위젯의 On Animation Finished 이벤트에서 끝난 애니메이션이 대상 애니메이션인지 확인하는 방법이 있습니다. 다만 애니메이션을 중지해도 끝남 알림이 올 수 있으므로, 창을 닫는 마무리 처리에서는 지금 정말 닫는 중인 상태인지도 함께 확인합니다.


메뉴가 서서히 나타나게 하기

위젯 블루프린트의 기본 개념에서 만든 WBP_MainMenu가 갑자기 튀어나오는 대신 1초 동안 서서히 나타나게 해 봅니다. 디자이너 탭에서 루트 Canvas Panel이나 그 안의 Vertical Box 같은 메인 패널을 선택해 Is Variable을 켜고 이름을 RootPanel로 정합니다. 그다음 애니메이션 창에서 +Animation으로 FadeInAnim을 추가하고, + Track으로 RootPanel을 고른 뒤 트랙의 + 버튼으로 Render Opacity 속성을 추가합니다. Canvas Panel이나 Vertical Box에는 텍스트용 Color And Opacity가 있다고 가정하지 않고, 패널 전체에 적용되는 Render Opacity를 씁니다.

키프레임은 두 개면 됩니다. 타임라인 헤드를 0.0초에 두고 Render Opacity를 0.0으로 정해 키를 추가하고, 헤드를 1.0초로 옮겨 Render Opacity를 1.0으로 바꾼 뒤 다시 키를 추가합니다. 이렇게 하면 0초부터 1초까지 패널이 투명한 상태에서 불투명해지는 애니메이션이 완성됩니다.

그래프 탭에서는 Event Construct 뒤에 Play Animation을 연결하고 In Animation에 FadeInAnim을 넣습니다. 위젯 블루프린트의 기본 개념에서 본 것처럼 Construct는 위젯을 다시 화면에 추가할 때 반복될 수 있다는 점을 기억해 둡니다. 화면에 처음 보이기 전에 깜빡이지 않도록 디자이너에서 RootPanel의 기본 Render Opacity를 0으로 맞춰 두고, 이 예제는 한 번 재생한 뒤 불투명도 1을 유지해야 하므로 Play Animation의 Restore State를 끕니다. 이제 플레이하면 메인 메뉴가 부드럽게 나타납니다.

재생 속도와 실제 시간

애니메이션에 기록한 구간의 길이와 실제로 재생되는 시간은 다를 수 있습니다. 같은 FadeInAnim을 Start at Time 0, Forward, 한 번 재생, Playback Speed 2.0으로 재생해 정상적으로 끝났다면, 1초 길이의 구간을 두 배 속도로 재생했으므로 실제 재생 시간은 1 / 2 = 0.5초입니다. 이 계산은 도중에 중지하거나 일시 정지하지 않고, 반복하거나 속도를 바꾸지도 않았다는 조건에서만 맞습니다.


보이지 않는 것과 입력을 받지 않는 것

닫기 애니메이션으로 버튼의 Render Opacity를 0으로 만들면 버튼은 화면에서 보이지 않습니다. 하지만 불투명도는 그려지는 모습만 바꾸는 표시 속성이라서, 보이지 않는 버튼도 여전히 클릭을 받을 수 있습니다. 투명해진 메뉴가 화면 위에 남아 아래쪽 게임 화면의 클릭을 가로채는 일이 이 때문에 생깁니다.

그래서 닫힌 UI는 애니메이션이 끝난 뒤 위젯의 Visibility를 Collapsed나 Hidden으로 바꾸거나, 화면에서 제거하거나, 활성 상태를 꺼서 입력을 받지 않게 해야 합니다. 애니메이션이 표시를, Visibility와 활성 상태가 입력을 맡는다고 나누어 생각하면 됩니다.


더 다듬는 기능

애니메이션을 더 다듬을 때 쓰는 기능도 있습니다. 여러 속성을 함께 움직일 때는 관련 트랙을 묶어 관리할 수 있고, 키프레임 사이의 값이 바뀌는 방식을 보간 곡선(interpolation curve)으로 조절해 선형(Linear), 가속과 감속(Ease In/Out), 직접 만든 곡선처럼 더 자연스러운 움직임을 만들 수 있습니다. 애니메이션의 특정 시점에 효과음 재생 같은 블루프린트 처리를 연결하는 이벤트 트랙은, 사용하는 엔진 버전의 위젯 애니메이션이 지원하는 범위에서 씁니다. 복잡한 UI 움직임은 짧은 애니메이션 여러 개를 조합해 만드는 편이 관리하기 쉽습니다.

애니메이션을 넣을 때는 플레이어를 위한 선택지도 함께 생각합니다. 움직임에 불편함을 느끼는 플레이어를 위해 애니메이션을 줄이는 설정을 제공하고, 버튼을 연달아 눌렀을 때 재생을 처음부터 다시 시작할지 무시할지도 정해 둡니다. 정하지 않으면 같은 애니메이션이 겹쳐 재생되어 엉뚱한 상태로 끝날 수 있습니다.


정리

  • UI 애니메이션은 위젯의 위치, 크기, 회전, 투명도, 색상을 시간에 따라 바꿔 피드백과 자연스러운 전환을 만듭니다.
  • 애니메이션 창의 +Animation으로 애니메이션을, + Track으로 대상 위젯과 속성 트랙을 추가하고, 키프레임으로 시각별 값을 기록합니다.
  • 그래프에서는 Play Animation의 Start at Time, Play Mode, Playback Speed, Num Loops to Play, Restore State로 재생을 제어합니다.
  • Play Animation의 일반 실행 출력은 재생 완료를 기다리지 않으므로, 끝난 뒤의 처리는 끝남 이벤트에 연결합니다.
  • 불투명도 0은 표시만 바꾸므로, 닫힌 UI가 입력을 받지 않게 하려면 Visibility나 활성 상태를 함께 바꿉니다.

연습 문제

1. 투명한 버튼의 입력

Render Opacity만 0으로 만든 버튼이 있고, Visibility와 활성 상태는 입력을 받도록 그대로 두었습니다. 이 버튼이 보이지 않는다는 이유만으로 클릭이 막혔다고 판단할 수 있을까요?

해설 보기

판단할 수 없습니다. 불투명도는 그려지는 모습을 바꾸는 표시 속성이고, 입력을 받지 않게 하는 상태 관리와는 다릅니다. 이 버튼은 보이지 않을 뿐 여전히 클릭을 받을 수 있습니다.

닫힌 UI라면 그 위젯의 Visibility와 활성 상태, 입력 경로까지 확인해야 합니다. 같은 맥락에서, 재생 시간을 0.5초로 계산했다고 Play Animation의 일반 실행 출력이 0.5초 뒤에 실행된다는 뜻도 아닙니다. 그 출력은 재생 시작 직후에 실행됩니다.

2. 느리게 재생한 애니메이션의 시간

2초 길이의 SlideInAnim을 Start at Time 0, Forward, 한 번 재생, Playback Speed 0.5로 재생했고, 도중에 중지하거나 속도를 바꾸지 않았습니다. 정상적으로 끝났다면 실제 재생 시간은 얼마일까요? Num Loops to Play를 0으로 바꾸면 어떻게 될까요?

해설 보기

2초 구간을 절반 속도로 재생하므로 실제 재생 시간은 2 / 0.5 = 4초입니다.

Num Loops to Play를 0으로 바꾸면 무한 반복이 되어, 멈추라고 지시하기 전까지 애니메이션이 끝나지 않습니다. 이때는 끝남 이벤트를 기다려 다음 처리를 하는 구조가 동작하지 않으므로, 반복 애니메이션은 Stop Animation으로 멈추는 시점을 따로 정해 두어야 합니다.

3. 닫기 애니메이션이 보이지 않음

닫기 버튼의 On Clicked에서 Play Animation으로 FadeOutAnim을 재생하고, 그 실행 출력에 바로 Remove from Parent를 연결했습니다. 그런데 창이 서서히 사라지지 않고 즉시 없어집니다. 왜 그럴까요? 어떻게 고쳐야 할까요?

해설 보기

Play Animation의 일반 실행 출력은 재생을 시작한 직후 곧바로 실행되기 때문입니다. 애니메이션이 첫 프레임을 그리기도 전에 Remove from Parent가 위젯을 화면에서 떼어 내므로, 사라지는 움직임을 볼 수 없습니다.

Bind to Animation Event로 FadeOutAnim의 끝남 이벤트에 커스텀 이벤트를 등록하거나 On Animation Finished에서 끝난 애니메이션이 FadeOutAnim인지 확인한 뒤, 그 이벤트에서 Remove from Parent를 호출합니다. 중지로도 끝남 알림이 올 수 있으므로, 닫는 중이라는 상태 변수를 함께 확인하면 더 안전합니다.

위젯 애니메이션을 만들고 키프레임을 추가하는 방법은 언리얼 엔진 공식 문서의 UMG 위젯 애니메이션에서 확인할 수 있습니다.

다음 글 UI와 게임플레이 기본 상호작용에서는 UI의 버튼 입력을 게임 로직으로 전달하고, 게임의 상태 변화를 UI에 반영하는 연결 방법을 다룹니다.