Class GameDev* SheepAdult

[Unreal Engine] Widget을 통한 UI 생성 / 삭제, Widget 변수 사용 본문

Unreal Project

[Unreal Engine] Widget을 통한 UI 생성 / 삭제, Widget 변수 사용

SheepAdult 2022. 1. 11. 16:37

+ 2023.08.01 수정

 

* 본문에서는 Widget의 UI는 블루프린트 내에서 수정했다.

아이템에 대한 정보를 UI로 띄우려면 Widget을 사용한다. 먼저 UserWidget c++클래스를 하나 생성한다.

 

그리고 생성한 c++클래스의 이름에 맞는 블루프린트 클래스를 생성한다. 예를 들어 c++ 클래스 이름을ItemDetailViewWidget으로 생성한 뒤 블루프린트 클래스 생성을 누르고 모든 클래스에서 검색을 해보면

 

이러한 블루프린트 클래스가 있을 것이다. 이 블루프린트 클래스를 생성하고 Widget 변수와의 상호작용을 테스트하기 위해 텍스트 하나를 만들고 변수로 지정해줬다. (변수로 지정은 굳이 해줄 필요 없다.)

 

텍스트 생성

 

다른 스크립트에서의 사용을 위해 변수로 설정

 

 그리고 위에서 만든 텍스트 변수와 이름이 똑같은 변수를 Widget.h파일에도 똑같이 선언해 준다. 이 때 "meta = (BindWidget)"을 써줘 위젯과 바인딩을 해줘야 한다. 만약 변수 이름이 다를 경우, 위젯 블루프린트에서 에러가 날 것이므로 똑같이 해줘야 한다.

// Widget.h
class UTextBlock;

private:
	UPROPERTY(meta = (BindWidget))
		UTextBlock* ItemText;
   
public:
	FORCEINLINE UTextBlock* GetItemText() { return ItemText; };

> FORCEINLINE 설명 링크

 

 

그리고 아래와 같이선언해 줬다. WidgetClass는 디테일 창에서 직접 넣어줄 블루프린트 클래스이고 Widget에 WidgetClass를 넣어줄 것이다. 만약 위젯을 블루프린트로 생성했다면 WBP(위젯 블루프린트)를 넣어 줘야한다.

// Character.h
UPROPERTY(EditAnywhere, Category = "Widget")
	TSubclassOf<UUserWidget> ItemWidgetClass;
UPROPERTY()
	class Widget* ItemWidget;

> TSubclassOf 설명 링크

 

그 후 WidgetClass가 유효한지 검사한 후 CreateWidget 함수로 Widget을 생성 한 후 Widget 변수에 넣어준다. 잘 넣어줬다면 AddToViewport 함수로 창에 띄운다. 그리고 Widget이 열려있는 상태라면 RemoveFromParent로 Widget을 삭제해줬다. Text 변수인 ItemText의 Text도 바꿔준다. 아래처럼 SetText로 바꿔주면 된다. ItemTagText는 FString이다.

// Character.cpp
void ACharacter::Interact()
{
	// bool값 방식이 아닌, 위젯 자체의 OnDestruct에서 관리해도 된다.
    if (!bIsWatchingItemDetailView)
    {
        if (ItemWidgetClass)
        {
            ItemWidget = Cast<UItemDetailViewWidget>(CreateWidget(GetWorld(), ItemWidgetClass));
            if (ItemWidget)
            {
            	// 함수화 해주는 것이 좋아보이지만 기능 구현만을 위해 풀어 썼다.
            	ItemWidget->GetItemText()->SetText(FText::FromString(ItemTagText));
                ItemWidget->AddToViewport();
            }
        }
    }
    else
    {
        Widget->RemoveFromParent();
    }
    isWatchingItemDetailView = !isWatchingItemDetailView;
}

 

 

결과 :