모든 게임 내의 여러 UI 오브젝트를 메뉴시스템으로 종속시키려고한다.

 

게임 -> 메뉴시스템 (컴파일 타임)

메뉴시스템 <-> 게임 (양방향 호출, 런타임 종속성)

 

 

Unreal Interface C++ 생성

추가는 했지만 핫리로드 컴파일이 실패한경우 이전 글에서 다룬것처럼 VS를 열어 수정한다.

#include "MenuInterface.h"

Cpp 파일을 위와같이 수정한다.

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "UObject/Interface.h"
#include "MenuInterface.generated.h"

// 두개의 클래스가 자동 생성됨
// 아래의 클래스는 수정하지 말것.
// This class does not need to be modified.
UINTERFACE(MinimalAPI)
class UMenuInterface : public UInterface
{
	GENERATED_BODY()
};

/**
 * 
 */

// 다이아몬스 상속 문제를 해결
class PUZZLEPLATFORMS_API IMenuInterface
{
	GENERATED_BODY()

	// Add interface functions to this class. This is the class that will be inherited to implement this interface.
public:

	//오버라이드 할 함수를 이곳에 적는다
	//GameInstance 에서 구현을 원하기 때문에 순수 가상함수로 정의
	virtual void Host() = 0;

};

아래 클래스에 오버라이드할 함수를 적는다, 단 가상함수로 적을것.

 

 

UI를 델리게이트 한 MainMenu.h에 다음과 같은 헤더를 포함시킨다.

#include "MenuInterface.h"

 

private:
	//...

	//포함한 헤더의 인터페이스 변수 추가
	IMenuInterface* MenuInterface;

변수 추가.

 

//델리게이트 된 함수, Host버튼이 클릭되면 해당 함수가 호출된다
void UMainMenu::BTN_HostOnClicked()
{
	if (MenuInterface != nullptr)
	{
		MenuInterface->Host();
	}
}

델리게이트한 해당 함수에서 메뉴인터페이스가 있는지 확인 후 함수를 호출한다.

 

게임 인스턴스에서도 동일하게 헤더를 포함시킨다.

#include "MenuSystem/MenuInterface.h"

폴더명이 다르면 경로를 추가해준다.

 

인스턴스 클래스에 IMenuInterface를 상속시킨다.

UCLASS()
//class PUZZLEPLATFORMS_API UPuzzlePlatformsGameInstance : public UGameInstance
class PUZZLEPLATFORMS_API UPuzzlePlatformsGameInstance : public UGameInstance, public IMenuInterface

 

MainMenu.h에서 Setter을 지정한다

UCLASS()
class PUZZLEPLATFORMS_API UMainMenu : public UUserWidget
{
	GENERATED_BODY()

public:
	//Setter을 지정
	void SetMenuInterface(IMenuInterface* menuInterface);

protected:
	virtual bool Initialize();

MainMenu.cpp에서 함수를 정의한다.

void UMainMenu::SetMenuInterface(IMenuInterface* menuInterface)
{
	this->MenuInterface = menuInterface;
}

 

PuzzlePlatformsGameInstance.cpp에서

#include "MenuSystem/MainMenu.h"를 포함시킨다

그리고 UUserWidget을 UMainMenu로 변경시키고

맨아래에 SetMenuInterfece함수를 호출한다.

void UPuzzlePlatformsGameInstance::LoadMenu()
{

	UE_LOG(LogTemp, Warning, TEXT("FuncTest"));


	//생성자에서 mMenuClass가 할당되지 않을경우 리턴한다. (이전 장에서 다룸)
	if (!ensure(mMenuClass != nullptr)) return;


	//CreateWidget<UUserWidget>함수로 위젯을 생성한다.
	UMainMenu* Menu = CreateWidget<UMainMenu>(this, mMenuClass);

	if (!ensure(Menu != nullptr)) return;

	//UUserWidget::AddToViewport()로 뷰포트에 호출한다.
	Menu->AddToViewport();

	//플레이어 컨트롤러 획득
	APlayerController* PlayerController = GetFirstLocalPlayerController();
	if (!ensure(PlayerController != nullptr)) return;

	//UI 입력모드 구조체 로컬 선언
	FInputModeUIOnly InputModeData;
	
	//DoNotLock 옵션으로 마우스 락 설정을 한다.
	InputModeData.SetLockMouseToViewportBehavior(EMouseLockMode::DoNotLock);

	//PlayerController->SetInputMode
	InputModeData.SetWidgetToFocus(Menu->TakeWidget());

	PlayerController->SetInputMode(InputModeData);

	Menu->SetMenuInterface(this);
}

 

--> MenuInterface에서 선언한 가상함수는 GameInstance에서 선언한다(상속 관계)

 

bonnate