[C++] UMG 바인딩하기 2

Woogle·2022년 11월 9일
0

언리얼 엔진 5

목록 보기
24/59
post-thumbnail

이번에는 게임오버 UI, Restart 버튼, Quit 버튼의 기능을 C++로 만들어보았다.


📄 Widget

✏️ Blueprint

  • Button_Restart, Button_Quit을 만든다.
  • 지금부터 이 블루프린트 내용을 C++에 옮겨보자.

✏️ C++

헤더 파일

#pragma once

#include "CoreMinimal.h"
#include "Blueprint/UserWidget.h"
#include "GameOverWidget.generated.h"

UCLASS()
class MYSHOOTINGCPP_API UGameOverWidget : public UUserWidget
{
	GENERATED_BODY()
	
public:
	virtual void NativeConstruct() override;	// BeginPlay()처럼 사용

	UPROPERTY(EditAnywhere, meta = (BindWidget))
	class UButton* Button_Restart;

	UPROPERTY(EditAnywhere, meta = (BindWidget))
	class UButton* Button_Quit;

	UFUNCTION()
	void OnRestart();

	UFUNCTION()
	void OnQuit();
};

소스 파일

#include "GameOverWidget.h"
#include <Kismet/GameplayStatics.h>
#include <Components/Button.h>
#include <Kismet/KismetSystemLibrary.h>

void UGameOverWidget::NativeConstruct()
{
	Super::NativeConstruct();

	// 함수 바인딩
	Button_Restart->OnClicked.AddDynamic(this, &UGameOverWidget::OnRestart);
	Button_Quit->OnClicked.AddDynamic(this, &UGameOverWidget::OnQuit);
}

void UGameOverWidget::OnRestart()
{
	FString levelName = UGameplayStatics::GetCurrentLevelName(GetWorld());
	UGameplayStatics::OpenLevel(GetWorld(), FName(*levelName));
}

void UGameOverWidget::OnQuit()
{
	UKismetSystemLibrary::QuitGame(GetWorld(), GetWorld()->GetFirstPlayerController(), EQuitPreference::Quit, false);
}

📄 Game Mode

✏️ Blueprint

  • C++로 옮길 내용

✏️ C++

헤더 파일

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/GameModeBase.h"
#include "MyShootingCppGameModeBase.generated.h"

UCLASS()
class MYSHOOTINGCPP_API AMyShootingCppGameModeBase : public AGameModeBase
{
	GENERATED_BODY()

protected:
	// Called when the game starts or when spawned
	virtual void BeginPlay() override;

public:
	int score = 0;
	void AddScore(int value);

	UPROPERTY(EditAnywhere)
	TSubclassOf<class UScoreWidget> scoreWidgetFactory;

	class UScoreWidget* scoreWidget;

	UPROPERTY(EditAnywhere)
	TSubclassOf<class UGameOverWidget> gameOverWidgetFactory;	// 생성할 위젯의 설계도

	class UGameOverWidget* gameOverWidget;	// 위젯을 담아둘 그릇

	void ShowGameOverUI();
};

소스 파일

#include "MyShootingCppGameModeBase.h"
#include <Blueprint/UserWidget.h>
#include "ScoreWidget.h"
#include <Components/TextBlock.h>
#include "GameOverWidget.h"

void AMyShootingCppGameModeBase::BeginPlay()
{
	scoreWidget = CreateWidget<UScoreWidget>(GetWorld(), scoreWidgetFactory);
	scoreWidget->AddToViewport();

    // 게임오버 위젯을 미리 만들어둔다 (아직 화면에 띄우지는 않음)
	gameOverWidget = CreateWidget<UGameOverWidget>(GetWorld(), gameOverWidgetFactory);

	// 마우스 커서를 숨기고, 입력 모드를 GameOnly로
	GetWorld()->GetFirstPlayerController()->SetShowMouseCursor(false);
	GetWorld()->GetFirstPlayerController()->SetInputMode(FInputModeGameOnly());
}

void AMyShootingCppGameModeBase::AddScore(int value)
{
	score = score + value;
	scoreWidget->TextBlock_Score->SetText(FText::AsNumber(score));
}

void AMyShootingCppGameModeBase::ShowGameOverUI()
{
	// 게임오버 위젯을 화면에 띄운다
	gameOverWidget->AddToViewport();

	// 마우스 커서를 띄우고, 입력 모드를 UIOnly로
	GetWorld()->GetFirstPlayerController()->SetShowMouseCursor(true);
	GetWorld()->GetFirstPlayerController()->SetInputMode(FInputModeUIOnly());

	// 일시정지
	GetWorld()->GetFirstPlayerController()->SetPause(true);
}
  • 컴파일 후에는 Blueprint의 부모 클래스를 C++ 파일로 지정해주고, gameOverFactory에 WBP를 지정한다.

📄 Player

✏️ C++

소스 파일

void APlayerPawn::OnAttacked(int damage)
{
	currentHp -= damage;

	OnUpdateHealth(currentHp);
	if (currentHp <= 0)
	{
		// 게임모드를 가져와서 게임오버 UI 띄우는 함수를 호출
		auto gameMode = Cast<AMyShootingCppGameModeBase>(GetWorld()->GetAuthGameMode());
		gameMode->ShowGameOverUI();
		this->Destroy();
	}
}

📄 결과

  • Player가 Enemy에 충돌하여 체력이 0 이하가 되면 게임오버 UI가 화면에 띄워진다.
  • 마우스 커서도 띄워지고, 일시정지도 된다.
profile
노력하는 게임 개발자

0개의 댓글