개발 · 컴퓨터공학 / / 2022. 2. 8. 20:42

Learning Unreal 4 언리얼 공부일지 - UMG 사용해보기

728x90
반응형

UMG을 처음 들어보았는데 이는 stand for Unreal Motion Graphic이다.

단어만 보면 너무 포괄적이라 무슨 말인지 모르겠는데, 의미적으로는 UI로 통하는 듯 하다.

 

참고로 UMG를 사용하기 위해서는 빌드세팅 C#파일에 'UMG' string을 추가해야한다.

새로운 일인칭 프로젝트를 생성해서 '유저인터페이스 → 위젯 블루프린트'를 만들고, class로 UserWidget을 상속한 클래스를 생성하자.

 

// MyHUD.h

UCLASS()
class FIRSTPERSONEXAMPLE_API UMyHUD : public UUserWidget
{
	GENERATED_BODY()
public:
	// widget 프로퍼티 선언
	UPROPERTY(meta = (BindWidget))
	class UTextBlock* AmmoText;
};

UserWidget 클래스에는 TextBlock 프로퍼티를 선언한다.

 

// FirstPersonExampleGamemode.h

UCLASS(minimalapi)
class AFirstPersonExampleGameMode : public AGameModeBase
{
	GENERATED_BODY()

public:
	AFirstPersonExampleGameMode();

public:
	// widget의 클래스를 담음
	UPROPERTY()
	TSubclassOf<UUserWidget> HUD_Class;

	// widget의 주소
	UPROPERTY()
	UUserWidget* CurrentWidget;
};

 

GameMode 클래스의 header에는 widget의 클래스, widget이 들어갈 주소를 담는 프로퍼티를 선언한다.

// FirstPersonExampleGameMode.cpp

AFirstPersonExampleGameMode::AFirstPersonExampleGameMode()
	: Super()
{
	/.../
    
	// MyHUD 오브젝트 찾아오기
	static ConstructorHelpers::FClassFinder<UMyHUD> UI_HUD(TEXT("WidgetBlueprint'/Game/WBP_HUD.WBP_HUD_C'"));
	if (UI_HUD.Succeeded())
	{
		HUD_Class = UI_HUD.Class;

		// HUD_Class에 해당하는 class의 widget을 만드는 함수
		CurrentWidget = CreateWidget(GetWorld(), HUD_Class);
		if (CurrentWidget)
		{
			// view port로 widget을 추가
			CurrentWidget->AddToViewport();
			// CurrentWidget->RemoveFromViewport();
		}
	}
}

GameMode.cpp에서는 MyHUD오브젝트를 가져와서 헤더에서 선언한 widget의 클래스를 생성하여 담고 view에 추가한다.

 

 

// FirstPersonExampleCharacter.h

UCLASS(config=Game)
class AFirstPersonExampleCharacter : public ACharacter
{

protexted:
	// UI 새로고침 함수
	void RefreshUI();
    
	/.../
    
    // Ammo 관련 변수 선언
	int32 AmmoCount = 5;
	int32 MaxAmmoCount = 5;
}

FPS 프로젝트를 생성하면 기본적으로 포함되어있던 Character 클래스의 헤더에 Ammo변수를 선언한다.

RefreshUI함수를 통해 UI 내용을 새로고침하는 함수를 선언한다.

 

// FirstPersonExampleCharacter.cpp

/.../

// 헤더 추가
#include "FirstPersonExampleGameMode.h" 
#include "MyHUD.h"
#include "Components/TextBlock.h"

/.../
void AFirstPersonExampleCharacter::BeginPlay()
{
	/.../
	// UI 새로고침
	RefreshUI();
}
/.../

void AFirstPersonExampleCharacter::RefreshUI() 
{
	AFirstPersonExampleGameMode* GameMode = Cast<AFirstPersonExampleGameMode>(UGameplayStatics::GetGameMode(GetWorld()));
	if (GameMode)
	{
		UMyHUD* MyHUD = Cast<UMyHUD>(GameMode->CurrentWidget);
		if (MyHUD)
		{
			const FString AmmoStr = FString::Printf(TEXT("Ammo %01d/%01d"), AmmoCount, MaxAmmoCount);
			MyHUD->AmmoText->SetText(FText::FromString(AmmoStr));
		}
	}
}

void AFirstPersonExampleCharacter::OnFire()
{
	// Ammo가 없는 경우 쏘지않도록
	if (AmmoCount <= 0)
		return;

	AmmoCount--;
    	// UI 새로고침
	RefreshUI();

	// GameMode 가져오기
	AFirstPersonExampleGameMode* GameMode = Cast<AFirstPersonExampleGameMode>(UGameplayStatics::GetGameMode(GetWorld()));
	if (GameMode)
	{
		UMyHUD* MyHUD = Cast<UMyHUD>(GameMode->CurrentWidget);
		if (MyHUD)
		{
			const FString AmmoStr = FString::Printf(TEXT("Ammo %01d/%01d"), AmmoCount, MaxAmmoCount);
			MyHUD->AmmoText->SetText(FText::FromString(AmmoStr));
		}
	}
    
    /.../
}

/.../

cpp에는 Ammo의 Count관련 처리 및 GameMode를 가져와서 GameMode 안의 HUD에 Ammo관련 Text를 띄우는 동작을 작성한다. Refresh로 게임시작시 미리 UI Text를 새로고침한다.

 

코드를 작성하고 컴파일 후 안되길래 뭘 빼먹었지.. 하고 있었는데, 알고보니 아직 블루프린트에 익숙하지 않은 모양인지 HUB 블루프린트 클래스에서 '클래스 세팅 → 부모 클래스'를 설정해서 블루프린트 클래스의 부모를 위에서 작성한 MyHUD코드로 바꾸는 것을 빼먹었다.

728x90
반응형
  • 네이버 블로그 공유
  • 네이버 밴드 공유
  • 페이스북 공유
  • 카카오스토리 공유