[CommonUI] PauseMenu

김여울·2025년 12월 22일

내일배움캠프

목록 보기
134/139

게임 안에서 ESC 누르면 오디오, 그래픽 설정할 수 있는 정지메뉴 만들기

위젯 만들기 (WBP_Pause)

구조

- Setting (Audio (+ PlayerVolume), Graphics)
- Continue
- MainMenu (-> ConfirmationDialogue)

버튼은 BP로, 위젯 스택/레이어 관리는 C++로 나누기

  • 위젯은 CommonActivatableWidget / 버튼은 CommonButtonBase로 만들기

  • Setting 안에는 ChangePanel로 만들어야하니까
    기존 MainMenu에서 썼던 WBP_Audio, WBP_Graphics 가져오기


함수

Setting 누르면 버티컬 박스 가져오기 (ChangePanel)

함수 안 만들면 Setting 눌러도 OptionPanel이 안 나온다!

확인메세지 Yes 누르면 MainMenu로 돌아가기

void HandleMainMenuConfirmed(bool bYes);
C++ 먼저 만들기


Layer 등록하기

UITags.hUITags.cpp 에서 Request와 Layer 설정하기

데이터 에셋에 연결하기 (DA_LNMaps)



Enhanced Input 설정 (IA & IMC & Character)

InputAction 만들기

IA_Pause

IMC에서 키 매핑 하기

에디터 설정을 계속해도 ESC 누르면 자꾸 PIE 정지로 연결돼서 임시로 P
키에 연결

캐릭터에 연결하기

Character (C++)

// LNCharacter.h
protected:
    UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "LN|Input")
    TObjectPtr<UInputAction> PauseAction; // ESC 키 Input Action

    void OnPauseInput(const FInputActionValue& Value); // 일시정지 입력 처리 함수
    
    
// LNCharacter.cpp    
void ALNCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
	Super::SetupPlayerInputComponent(PlayerInputComponent);

	if (Controller && Controller->IsLocalController())
	{
		if (UEnhancedInputComponent* EnhancedInputComponent = Cast<UEnhancedInputComponent>(PlayerInputComponent))
		{
			// ...
			EnhancedInputComponent->BindAction(PauseAction,  ETriggerEvent::Started, this, &ThisClass::OnPauseInput);
		}
	}
}

void ALNCharacter::OnPauseInput(const FInputActionValue& Value)
{
	if (UGameInstance* GI = GetGameInstance())
	{
		if (ULNUIManageSubsystem* UIManager = GI->GetSubsystem<ULNUIManageSubsystem>())
		{
			static FGameplayTag OverlayLayer = FGameplayTag::RequestGameplayTag(TEXT("UI.Layer.Overlay"));
			UCommonActivatableWidget* ActiveWidget = UIManager->GetActiveWidgetFromLayer(OverlayLayer);

			if (ActiveWidget)
			{
				return;
			}

			static FGameplayTag PauseRequestTag = FGameplayTag::RequestGameplayTag(TEXT("UI.Request.PauseMenu"));
			UIManager->ShowWidget(PauseRequestTag);

			if (APlayerController* PC = Cast<APlayerController>(GetController()))
			{
				UIManager->SetInputModeUIOnly(PC);
			}
		}
	}
}

BP_Character

캐릭터 블루프린트 디테일 창에서 IA_Input 할당하기


PauseMenuWidget(C++)

// PauseMenuWidget.h
protected:
	virtual void NativeOnActivated() override;
	virtual void NativeOnDeactivated() override;

	ULNUIManageSubsystem* GetUIManager() const;
  
  	UFUNCTION(BlueprintCallable, Category = "LN|UI|Pause")
	void HandleMainMenuConfirmed(bool bYes);
  
  
// PauseMenuWidget.cpp
#include "UI/Subsystem/LNUIManageSubsystem.h"
#include "Kismet/GameplayStatics.h"

void UPauseMenuWidget::NativeOnActivated()
{
	Super::NativeOnActivated();

	SetVisibility(ESlateVisibility::Visible);

	if (UWorld* World = GetWorld())
	{
		APlayerController* PC = GetOwningPlayer();
		if (!PC)
		{
			return;
		}

		if (ULNUIManageSubsystem* UIManager = GetUIManager())
		{
			UIManager->SetInputModeUIOnly(PC, this, false);
		}

		UGameplayStatics::SetGamePaused(World, true);
	}
}

void UPauseMenuWidget::NativeOnDeactivated()
{
	Super::NativeOnDeactivated();

	SetVisibility(ESlateVisibility::Collapsed);

	if (UWorld* World = GetWorld())
	{
		APlayerController* PC = GetOwningPlayer();
		if (!PC)
		{
			return;
		}

		if (ULNUIManageSubsystem* UIManager = GetUIManager())
		{
			UIManager->SetInputModeGameOnly(PC);
		}

		UGameplayStatics::SetGamePaused(World, false);
	}
}

ULNUIManageSubsystem* UPauseMenuWidget::GetUIManager() const
{
	if (UGameInstance* GI = GetGameInstance())
	{
		return GI->GetSubsystem<ULNUIManageSubsystem>();
	}

	return nullptr;
}
  
  void UPauseMenuWidget::HandleMainMenuConfirmed(bool bYes)
{
	if (!bYes)
	{
		return;
	}

	if (UGameInstance* GI = GetGameInstance())
	{
		if (ULNUIManageSubsystem* UIManager = GI->GetSubsystem<ULNUIManageSubsystem>())
		{
			DeactivateWidget();

			static FGameplayTag MainMenuTag = FGameplayTag::RequestGameplayTag("UI.Request.MainMenu");
			UIManager->ShowWidget(MainMenuTag);
		}
	}

	UGameplayStatics::OpenLevel(this, FName("LV_MainMenu"));
}

나중에 해야할 일

  • IMC 변경하기 : PESC
  • 키 매핑 연결해서 IsBackHandler로 자동 버튼 처리하기
    • Is Back Handler : True로 체크
    • Display in Action Bar : True로 체크하면 하단 액션바에 "돌아가기" 표시됨

0개의 댓글