언어:
페이지 정보
엔진 버전:
언리얼 엔진

5. 2차 메뉴 제작

언리얼 엔진
  1. 콘텐츠 브라우저 에서 아까 만든 "NewGameMenu" 애셋을 찾아 엽니다. 이 메뉴에는 이름 입력 텍스트 박스 와, 이름을 입력하기 전까지는 누를 수 없는 '게임 플레이' 버튼, 메인 메뉴로 돌아가는 버튼 이 들어있습니다.

  2. 이름 입력 박스를 만들기 위해, 레이아웃에 (텍스트 블록 이 아닌) Text Box (텍스트 박스) 를 끌어 놓습니다.

    CreateTextEntryBox.png

  3. 텍스트 박스 환경설정은 다음과 같이 합니다:

    • 이름을 NameTextEntry 로 바꿉니다.

    • 위치는 (325, 200) 입니다. 텍스트 박스 왼쪽에 위치한 텍스트 블록 을 남겨둡니다.

    • 크기는 250x40 입니다.

    • ("Style" 제목 아래) 폰트 크기는 20 입니다.

    TextBoxDetails.png

  4. 이전 메뉴에서 버튼 을 만들었던 것과 같은 방식으로 텍스트 블록 라벨이 있는 게임 플레이 버튼 을 만들면 됩니다.

    • 버튼의 경우: 이름은 PlayGameButton, Position 은 200, 300, Size 는 200, 100 으로 변경합니다.

    • 텍스트 블록의 경우: 이름을 PlayGameText 로, Visibility 를 Hit Test Visible 로 변경한 다음 PlayGameButton 위에 끌어놓습니다.

  5. 게임 플레이 버튼 에는 특별한 기능이 있습니다. 텍스트 박스 에 입력된 이름이 공백이 아닐 때만 활성화되는 것입니다. UMG 의 "바인드" 기능을 사용하여 (Behavior 섹션 아래) "Is Enabled" 칸에 새로운 함수를 만들면 됩니다.

    PlayGameButtonDetails.png

    게임에서 쓸 수 있는 플레이어 이름을 결정하는 데 복잡한 규칙이 있다거나, 이름을 C++ 변수로 저장할 필요가 있는 경우, 게임 모드UFUNCTION 또는 프로젝트 내 어딘가에 스태틱 함수로 노출시켜야 할 것입니다. 하지만 이름 문자열이 공백만 아니면 되니, 위젯 에서 바로 스크립트를 짜 주면 되겠습니다.

  6. 오직 텍스트 박스 가 공백이 아닐 경우에만 버튼 이 활성화되었는지 확인하려면, 텍스트 박스 에서의 텍스트를 스트링으로 변환한 다음 길이가 0 보다 큰지 검사하면 됩니다. 로직은 이렇습니다:

    PlayGameButtonEnableFunction.png

  7. 여기서 메인 메뉴로 돌아나갈 수 있도록 버튼 을 하나 더 추가해 봅시다. 메인 메뉴에서 게임 플레이 버튼 과 비슷하지만, 위치 기준이 좌상단이 아닌 우하단 구석이 될 것입니다. 그러기 위해서는, 버튼디테일 패널 에서 "앵커" 드롭다운을 클릭한 다음, 팝업 메뉴에서 우하단 부분을 나타내는 모양을 선택합니다.

    • 이름을 MainMenuButton 으로 바꿉니다.

    • Position 을 -400, -200 으로 설정합니다.

    • Size 를 200x100 으로 설정합니다.

    SelectAnchor.png

    앵커를 우하단 구석으로 지정한다고 크기나 위치값 작동 방식이 변하는 것은 아니므로, 위치 값을 음수로 해 줘야 화면에 보이게 됩니다. 크기 값은 양수로 둡니다.

  8. 이제 OnClicked 이벤트를 한 번 더 추가하는 것으로 새 버튼 에 스크립트를 추가하겠습니다. 메인 메뉴 버튼 은 단순히 메인 메뉴 위젯 을 로드하는 반면, 게임 플레이 버튼ChangeMenuWidget 함수로의 호출에 새로운 위젯 을 전혀 제공하지 않는 것으로 메뉴를 비활성화시킵니다. 이는 실제 클래스 또는 애셋 이름 대신 "Select Class" (클래스 선택)이라 되어있는 문구로 알 수 있습니다.

    NewGameButtonBPs.png

    게임 플레이 버튼 으로 메뉴를 비활성화시킨 이후, 게임에서 더이상 아무것도 할 수 없게 됩니다. 보통 이 시점에서 첫 레벨을 로드하고, 오프닝 동영상을 재생한 뒤 을 스폰시켜 빙의하거나 하게 됩니다.

  9. 거의 아래와 같은 스크린샷이 두 개 생겼을 것입니다.

    FinalScreen.png

    FinalScreen2.png

완성 코드

HowTo_UMG.Build.cs

// Copyright 1998-2018 Epic Games, Inc. All Rights Reserved.

using UnrealBuildTool;

public class HowTo_UMG : ModuleRules
{
    public HowTo_UMG(TargetInfo Target)
    {
        PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "UMG" });

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

        // Uncomment if you are using Slate UI
        PrivateDependencyModuleNames.AddRange(new string[] { "Slate", "SlateCore" });

        // Uncomment if you are using online features
        // PrivateDependencyModuleNames.Add("OnlineSubsystem");
        // if ((Target.Platform == UnrealTargetPlatform.Win32) || (Target.Platform == UnrealTargetPlatform.Win64))
        // {
        //      if (UEBuildConfiguration.bCompileSteamOSS == true)
        //      {
        //          DynamicallyLoadedModuleNames.Add("OnlineSubsystemSteam");
        //      }
        // }
    }
}

HowTo_UMGGameMode.h

// Copyright 1998-2018 Epic Games, Inc. All Rights Reserved.

#pragma once

#include "Blueprint/UserWidget.h"
#include "GameFramework/GameModeBase.h"
#include "HowTo_UMGGameMode.generated.h"

/**
    * 
    */
UCLASS()
class HOWTO_UMG_API AHowTo_UMGGameMode : public AGameModeBase
{
    GENERATED_BODY()

public:
    /** Remove the current menu widget and create a new one from the specified class, if provided. */
    UFUNCTION(BlueprintCallable, Category = "UMG Game")
    void ChangeMenuWidget(TSubclassOf<UUserWidget> NewWidgetClass);

protected:
    /** Called when the game starts. */
    virtual void BeginPlay() override;

    /** The widget class we will use as our menu when the game starts. */
    UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UMG Game")
    TSubclassOf<UUserWidget> StartingWidgetClass;

    /** The widget instance that we are using as our menu. */
    UPROPERTY()
    UUserWidget* CurrentWidget;
};

HowTo_UMGGameMode.cpp

// Copyright 1998-2018 Epic Games, Inc. All Rights Reserved.

#include "HowTo_UMG.h"
#include "HowTo_UMGGameMode.h"

void AHowTo_UMGGameMode::BeginPlay()
{
    Super::BeginPlay();
    ChangeMenuWidget(StartingWidgetClass);
}

void AHowTo_UMGGameMode::ChangeMenuWidget(TSubclassOf<UUserWidget> NewWidgetClass)
{
    if (CurrentWidget != nullptr)
    {
        CurrentWidget->RemoveFromViewport();
        CurrentWidget = nullptr;
    }
    if (NewWidgetClass != nullptr)
    {
        CurrentWidget = CreateWidget<UUserWidget>(GetWorld(), NewWidgetClass);
        if (CurrentWidget != nullptr)
        {
            CurrentWidget->AddToViewport();
        }
    }
}

HowTo_UMGPlayerController.h

// Copyright 1998-2018 Epic Games, Inc. All Rights Reserved.

#pragma once

#include "GameFramework/PlayerController.h"
#include "HowTo_UMGPlayerController.generated.h"

/**
    * 
    */
UCLASS()
class HOWTO_UMG_API AHowTo_UMGPlayerController : public APlayerController
{
    GENERATED_BODY()

public:
    virtual void BeginPlay() override;
};

HowTo_UMGPlayerController.cpp

// Copyright 1998-2018 Epic Games, Inc. All Rights Reserved.

#include "HowTo_UMG.h"
#include "HowTo_UMGPlayerController.h"

void AHowTo_UMGPlayerController::BeginPlay()
{
    Super::BeginPlay();
    SetInputMode(FInputModeGameAndUI());
}