게임 메뉴 UI 디자인

언리얼 거토
|2025. 2. 7. 21:48

1. 메인 메뉴 레벨 생성

2. 메인 메뉴 위젯 블루프린트 제작

  • UMG (Unreal Motion Graphics)를 사용하여 메인 메뉴 UI를 구성.
  • 팔레트 기능을 활용하여 Canvas Panel (1920 x 1080)을 루트로 설정.
  • 내부 요소로 Start, Settings, Quit 버튼 및 텍스트 추가.

메뉴 디자인
메뉴 계층 구조

3. UI 애니메이션 추가

 

3-1. 게임 오버 애니메이션

  • GameOver 문구가 깜빡이는 효과를 애니메이션으로 구현.
  • Opacity 값을 조정하여 페이드 인/아웃 효과 적용.

 

3-2. 게임 오버 메뉴 슬라이드 애니메이션

  • 게임 오버 메뉴가 나타날 때 자연스럽게 슬라이드 인되는 애니메이션 추가.
  • Transform->Translation 값을 조정하여 부드러운 이동 효과 적용.

 

4. Build.cs 파일 수정

  • SpartaProject.Build.cs 파일을 수정하여 필요한 모듈을 추가.
  • PublicDependencyModuleNames에 UMG 모듈을 포함하여 UI 기능을 사용할 수 있도록 설정.
// Copyright Epic Games, Inc. All Rights Reserved.

using UnrealBuildTool;

public class SpartaProject : ModuleRules
{
	public SpartaProject(ReadOnlyTargetRules Target) : base(Target)
	{
		PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
	
		PublicDependencyModuleNames.AddRange(new string[] {
			"Core", 
			"CoreUObject", 
			"Engine", 
			"InputCore", 
			"EnhancedInput",
			"UMG"
		});

		PrivateDependencyModuleNames.AddRange(new string[] {  });

	}
}

SpartaProject.Build.cs

 

5. ASpartaPlayerController 클래스 메뉴 표시 기능 추가

  • ASpartaPlayerController에서 메뉴 UI를 표시하는 기능을 C++로 구현.
  • ShowMainMenu() 함수를 사용하여 게임 실행 시 메뉴 UI 표시.
#include "SpartaPlayerController.h"
#include "SpartaGameState.h"
#include "SpartaGameInstance.h"
#include "EnhancedInputSubsystems.h"
#include "Blueprint/UserWidget.h"
#include "Kismet/GameplayStatics.h"
#include "Components/TextBlock.h"
#include "Components/Button.h" //버튼 효과

ASpartaPlayerController::ASpartaPlayerController()

	MainMenuWidgetClass(nullptr),
	MainMenuWidgetInstance(nullptr)
{
}

void ASpartaPlayerController::BeginPlay()
{
	Super::BeginPlay();

	// 게임 실행 시 메뉴 레벨에서 메뉴 UI 먼저 표시
	FString CurrentMapName = GetWorld()->GetMapName();
	if (CurrentMapName.Contains("MenuLevel"))
	{
		ShowMainMenu(false);
	}
}

// 메뉴 UI 표시
void ASpartaPlayerController::ShowMainMenu(bool bIsRestart)
{
	// HUD가 켜져 있다면 닫기
	if (HUDWidgetInstance)
	{
		HUDWidgetInstance->RemoveFromParent();
		HUDWidgetInstance = nullptr;
	}

	// 이미 메뉴가 떠 있으면 제거
	if (MainMenuWidgetInstance)
	{
		MainMenuWidgetInstance->RemoveFromParent();
		MainMenuWidgetInstance = nullptr;
	}

	// 메뉴 UI 생성
	if (MainMenuWidgetClass)
	{
		MainMenuWidgetInstance = CreateWidget<UUserWidget>(this, MainMenuWidgetClass);
		if (MainMenuWidgetInstance)
		{
			MainMenuWidgetInstance->AddToViewport();

			bShowMouseCursor = true;
			SetInputMode(FInputModeUIOnly());
		}

		if (UTextBlock* ButtonText = Cast<UTextBlock>(MainMenuWidgetInstance->GetWidgetFromName(TEXT("StartButtonText"))))
		{
			if (bIsRestart)
			{
				ButtonText->SetText(FText::FromString(TEXT("Restart")));


			}
			else
			{
				ButtonText->SetText(FText::FromString(TEXT("Start")));
			}
		}

		if (bIsRestart)
		{
			//캔버스 애니매이션 실행
            	UFunction* PlayMenuAnimFunc = MainMenuWidgetInstance->FindFunction(FName("MenuSlideAnim"));
			if (PlayMenuAnimFunc)
			{
				MainMenuWidgetInstance->ProcessEvent(PlayMenuAnimFunc, nullptr);
			}
			//깜빡이는 Game Over 텍스트 애니매이션 실행
			UFunction* PlayAnimFunc = MainMenuWidgetInstance->FindFunction(FName("PlayGameOverAnim"));
			if (PlayAnimFunc)
			{
				MainMenuWidgetInstance->ProcessEvent(PlayAnimFunc, nullptr);
			}

			if (UTextBlock* TotalScoreText = Cast<UTextBlock>(MainMenuWidgetInstance->GetWidgetFromName("TotalScoreText")))
			{
				if (USpartaGameInstance* SpartaGameInstance = Cast<USpartaGameInstance>(UGameplayStatics::GetGameInstance(this)))
				{
					TotalScoreText->SetText(FText::FromString(
						FString::Printf(TEXT("Total Score: %d"), SpartaGameInstance->TotalScore)
					));
				}
			}
		}
	}
}


// 게임 시작 - BasicLevel 오픈, GameInstance 데이터 리셋
void ASpartaPlayerController::StartGame()
{
	if (USpartaGameInstance* SpartaGameInstance = Cast<USpartaGameInstance>(UGameplayStatics::GetGameInstance(this)))
	{
		SpartaGameInstance->CurrentLevelIndex = 0;
		SpartaGameInstance->TotalScore = 0;
	}

	UGameplayStatics::OpenLevel(GetWorld(), FName("BasicLevel"));
}

 

6. 시연 영상

 

 


✏️ 오늘은 메뉴 디자인을 해봤습니다. 드디어 뭔가 게임을 패키징 할 수 있는 능력이 생긴 것 같네요!