1. 개요
- UMG를 활용한 UI Animation 생성(슬라이드, 플리커링)
- HP 상태에 따라 게이지가 변화하는 형태의 HP바를 WidgetComponent를 이용해 3D위젯 형태로 생성
2-1. HUD(Heads Up Display)
기본적인 HUD 구성입니다. 게임 종료 문구, 점수 표시판, 재시작, 메인 메뉴 버튼으로 구성되어 있습니다. 게임 오버 텍스트 블록에 애니메이션을 적용하기 위해 화면 좌측 하단에서 다음 이미지에서 보이는 +Animation 버튼을 클릭합니다.
원하는 이름을 입력하고 해당 애니메이션을 클릭한 상태에서 우측 이미지에서 보이는 +Add를 눌러 GameOverText를 선택합니다.
위 이미지에서 +버튼을 눌러 Transform, Render Opacity를 각각 생성해 줍니다.
Render Opacity의 경우 슬라이드가 전인 0.75초 전까지는 1로 고정하였습니다. Transform에서 Translation의 Y값을 -500으로 하여 화면 밖에 위치해 있도록 하였습니다. 이후 0.75초에 값을 0으로 하여 자연스럽게 0.75초 간의 떨어지는 모션의 슬라이드 동작이 이루어 지게 하였습니다. 더불어 이 시점부터 Render Opacity 값을 1초부터 순서대로 0.2, 1, 0, 1로 하여 'Game Over!' 문구에 플리커링 효과를 주었습니다.
게임 오버 시 애니메이션이 자연스러울 수 있도록 기본적으로 Visibility 옵션을 hidden으로 설정해 두어 안 보이다가 게임 종료가 되면 Visible로 바꾸는 형태로 하였습니다.
(그렇지 않으면 게임 종료 메뉴가 뜰때 애니메이션을 통해 화면 가운데 자리로 와야할 'Game Over!' 문구가 가운데에 잠시 보였다가 애니메이션이 진행되면서 자연스럽지 못함, 점수도 마찬가지)
디자이너 탭에서 그래프 탭으로 넘어가 PlayGameOverAnim이라는 이름의 함수를 만들어 해당 함수 호출 시 방금 만든 Anim Time Over라는 이름의 애니메이션이 재생되도록 블루프린트를 구성합니다. 애니메이션이 진행될 때 Set Visibility 노드를 통해 Hidden으로 설정해두었던 것을 Visible로 변경합니다.
UFunction* PlayAnimFunc = GameOverMenuWidgetInstance->FindFunction(FName("PlayGameOverAnim"));
if (PlayAnimFunc)
{
GameOverMenuWidgetInstance->ProcessEvent(PlayAnimFunc, nullptr);
}
위와 같은 코드를 게임 종료 메뉴를 호출하는 함수에 추가해주어 게임 종료 메뉴가 호출될 때 애니메이션이 함께 호출되도록 합니다.
추가적으로 간단하게 버튼에 마우스가 호버링 중일 때 색깔을 바꾸는 기능도 넣어 보았습니다. Start, Exit 버튼을 클릭한 상태로 Details 창의 Style 카테고리에서 Hovered 카테고리를 보면 색이나 이미지 변경이 가능한데 Start 버튼은 색, Exit은 색과 이미지를 모두 변화하도록 설정하였습니다.
2-2 HP 바
HP 바의 경우 WBP_HP라는 이름의 Widget_Blueprint로 생성하였고, 다음과 같이 Progress Bar를 배치 후 Fill Color를 빨간색으로 설정하였습니다. 이번에 만들 UI는 3D 형태로 만들 것이기 때문에 Character클래스 헤더 파일에 다음과 같은 코드를 작성해 UWidgetComponent를 추가하였습니다.
UWidgetComponent* OverheadWidget;
이후 캐릭터의 생성자에서 해당 컴포넌트를 생성 및 초기화하는 코드를 작성합니다.
OverheadWidget = CreateDefaultSubobject<UWidgetComponent>(TEXT("OverheadWidget"));
OverheadWidget->SetupAttachment(GetMesh());
OverheadWidget->SetWidgetSpace(EWidgetSpace::Screen);
이후 HP가 변화하는 시점마다 호출되는 함수를 다음과 같이 작성했습니다.
#include "Components/ProgressBar.h" //헤더 파일 추가
void ASpartaCharacter::UpdateOverheadHP()
{
if (!OverheadWidget) return;
UUserWidget* OverheadWidgetInstance = OverheadWidget->GetUserWidgetObject();
if (!OverheadWidgetInstance) return;
if (UProgressBar* HPBar = Cast<UProgressBar>(OverheadWidgetInstance->GetWidgetFromName(TEXT("HealthBar"))))
{
HPBar->SetPercent(FMath::Clamp(Health / MaxHealth,0.0f,1.0f));
}
}
UProgressBar형태의 포인터 OverheadWidgetInstance의 GetWidgetFromName함수로 HealthBar라는 이름의 프로그레바를 가리키도록 만든 후에 SetPercent 함수를 호출하고 해당 값을 '현재 체력 / 최대 체력' 를 계산 후 FMath::Clamp로 0과 1사이의 값만 나오도록 제한하여 반영했습니다.
이후 블루프린트 형태로 감싼 캐릭터에서 Widget Class에 위에서 작성한 HealthBar가 있는 WBP_HP를 설정하였습니다.
3. 정리
처음 UI를 작성하려고 했을 때는 어떻게 해야할지 모르겠고 막막했었지만, 생각보다 툴이 잘되어 있어서 간단한 거라면 블루프린트로 그래프를 작성하여 만들 수도 있고 오늘 내가 한것처럼 소스코드에서도 그리 어렵지 않게 코드 몇줄을 적으면 끝나는 일이었다. 무엇보다 3D로 보여지는 WidgetComponent는 사용하기에 따라 아이템 설명을 게임 내에 입체적으로 띄울 수도 있고 여러 방면에 사용할 수 있을 것 같다.
애니메이션에 관련해서는 조금 고민해볼 거리가 있다면 자연스럽게 나타날 수 있도록 기본적으로 Visibility 옵션을 Hidden으로 해두었다가 애니메이션이 호출되면 그때 Visible로 다시 설정되게끔 하였는데, 이것도 처음 게임 오버 메뉴가 뜨는 순간에 보였다가 위에서 떨어지기 때문에 다른 방법이 필요할 것으로 보인다. 그래서 내가 떠올린 방안은 2가지이다.
첫번째는 게임 오버 텍스트의 기본 위치를 화면 밖으로 하고 Y값을 조절하여 원하는 위치에 오도록 애니메이션을 만드는 것이다. 두번째는 애니메이션에서 Opacity값을 적절한 시간대까지 0으로 설정하는 것이다. 이것도 아마 애니메이션이 이루어지는 적절한 시간대 이전에 보이지 않게 하면 아마 비슷한 결과물이 나올 것으로 보인다.
두가지 방법 중 더 나은 방법은 아마 첫번째일 것으로 보인다. 키에서 값을 조절하면서 게임 오버 메뉴에서의 'Game Over!'문구의 위치 조절이 쉽기도 하고 애초에 시기본 위치가 화면 밖이기 때문에 가운데에 잠시 생겼다가 사라지는 문제가 없을 것으로 보이기 때문이다. 반면에 두번째 방법의 경우는 애니메이션만 재생하는 것으로는 그 시간을 알기가 어렵기도 하고 게임을 여러번 실행해 가면서 적당한 시간을 찾아야 하기 때문에 그리 좋은 방법이 아닐 것 같다.
'언리얼엔진(UE)' 카테고리의 다른 글
[UE] 몬스터 AI 구현 #1 (0) | 2025.02.20 |
---|---|
[UE] 슬라이드 애니메이션 개선 (0) | 2025.02.14 |
[UE] 타이머 사용 시 유의 사항과 해결방법 (0) | 2025.02.12 |
[UE] TSubclassOf<>와 TSoftClassPtr<> (0) | 2025.02.07 |
[UE] 월드 좌표계와 로컬 좌표계 (World Space, Local Space) (1) | 2025.02.06 |