이전 글 보기
https://mountain-noroo.tistory.com/64
[언리얼] 학원 17일차: 버튼, RenderTexture
이전 글 보기 https://mountain-noroo.tistory.com/63 [언리얼] 학원 16일차: UMG: 언리얼 UI 이전 글 보기 https://mountain-noroo.tistory.com/62 [언리얼] 학원 15일차: AI Controller 플레이어 추적 이전 글 보기 https://mountain
mountain-noroo.tistory.com
액터 위 UI
플레이어나 몬스터의 이름과 체력을 표시하려고 캐릭터의 머리 위에 UI를 만드는 경우가 많다.
유니티에서는 구현이 은근히 까다로웠던 것으로 기억하는데 언리얼에서는 이를 간단하게 구현 가능하다.

우선 이름과 체력 바를 가진 UMG를 만든다.

UI를 추가할 몬스터에 Widget Component를 추가하고

디테일에서 위젯 컴포넌트에
어떤 위젯 클래스를 나타낼지 선택하고 사이즈를 정한다.
그리고 스페이스는 World와 Screen 두 가지 설정이 있는데
World는 월드 기준으로 transform을 나타낸다는 뜻으로 몬스터가 회전하면 ui도 회전되고 가까이 있으면 크게 보이고 멀리 있으면 작게 보인다.
Sceen은 화면 기준으로 transform을 나타낸다는 뜻으로 멀든 가깝든 회전하든 ui는 똑같은 크기로, 정면으로 보인다.
C++에서 위젯 컴포넌트의 위젯 가져오기
UMonInfo_Base* pMonInfoWidget = Cast<UMonInfo_Base>((m_WidgetComponent->GetWidget()));
위젯 컴포넌트에서 GetWidget 함수를 호출하면 지정된 위젯 클래스를 가져올 수 있다.
리스트
인벤토리를 만들기 위해서는 여러 아이템을 표시하는 기능을 필요로 한다. 아이템을 추가할 때마다 한 칸씩 손으로 만드는 것은 낭비이기 때문에 당연히 언리얼에서도 리스트를 사용한다.

리스트는 목록 뷰, 타일 뷰, 트리 뷰 세 가지가 있는데 보이는 형태가 다를 뿐 기능은 동일하다.

리스트를 추가하면 이런 경고 문구가 뜨며 컴파일이 되지 않는데 리스트로 만들 클래스가 정해지지 않아서이다.

이를 추가하기 위해 새로운 위젯을 만들어 목록 뷰에 어울리는 인벤토리 칸 하나를 만들었다.
그러나 여전히 엔트리 위젯 클래스에서는 아무것도 선택할 수 없을 것이다.

이를 엔트리 위젯 클래스로 만들기 위해서는 클래스 세팅 -> 디테일 창의 인터페이스에서
사용자 오브젝트 리스트 항목(User Object List Entry)이라는 인터페이스를 추가해주어야 한다.

그럼 이제 인벤토리에서 엔트리 위젯 클래스로 선택 가능해진다.
AddItem
현재 구현된 인벤토리는 모습만 존재할 뿐 실제로 아이템을 추가하는 기능은 아직 구현되지 않았다.
이는 ListView에 있는 AddItem이라는 함수를 통해 구현할 수 있다.
https://docs.unrealengine.com/5.1/en-US/API/Runtime/UMG/Components/UListView/AddItem/
UListView::AddItem
Adds an the item to the list
docs.unrealengine.com
이 함수를 호출하고 UObject을 상속받은 아이템 데이터를 전달하면 새 아이템을 리스트에 추가할 수 있다.
우선 아이템 데이터를 만들어보자.
UCLASS()
class UNREAL_3TH_API UInvenItemData : public UObject
{
GENERATED_BODY()
private:
FString m_IconImgPath;
FString m_ItemName;
int m_Count;
public:
void SetIconImgPath(const FString& _Path) { m_IconImgPath = _Path; }
const FString& GetIconImgPath() { return m_IconImgPath; }
void SetItemName(const FString& _Name) { m_ItemName = _Name; }
const FString& GetItemName() { return m_ItemName; }
void SetItemCount(int32 _Count) { m_Count = _Count; }
int32 GetItemCount() { return m_Count; }
public:
UInvenItemData();
~UInvenItemData();
};
아이콘이미지의 주소,
아이템 이름,
아이템 개수를 가진 데이터이다.
ListView가 UObject * Item을 매개변수로 받기 때문에 Item은 꼭 UObject를 상속하여야 한다.
중요한 것은 이 아이템을 받는 부분인데
앞서 Entry Widget Class로 지정하였던 위젯 클래스에도 UObject* 를 받는 함수를 만들어야 한다.
public:
// InventoryItemData 를 입력받아서 초기화하는 함수
UFUNCTION(BlueprintCallable)
void InitFromData(UObject* _Data);
void UInvenItem_Base::InitFromData(UObject* _Data)
{
UInvenItemData* pItemData = Cast<UInvenItemData>(_Data);
if (!IsValid(pItemData))
{
LOG(LogTemp, Error, TEXT("Iventory 위젯 입력 데이터가 올바르지 않습니다."));
return;
}
// 아이콘 이미지 세팅
FString IconPath = pItemData->GetIconImgPath();
UTexture2D* pTex2D = LoadObject<UTexture2D>(nullptr, *IconPath);
m_IconImg->SetBrushFromTexture(pTex2D);
// 아이템 이름 세팅
m_ItemName->SetText(FText::FromString(pItemData->GetItemName()));
// 아이템 수량 세팅
m_ItemCount->SetText(FText::FromString(FString::Printf(TEXT("%d"), pItemData->GetItemCount())));
}
받아온 UObject* 타입 데이터를 원하는 데이터에 맞게 다운 캐스팅하고
이 데이터에서 이미지 주소, 이름, 수량을 받아와 엔트리 위젯에 세팅해 주는 역할을 하고 있다.

UFUNCTION 매크로를 사용한 부분에서 눈치챘겠지만
블루프린트에서 Object Set 이벤트에 방금 만든 함수를 연결해 줘야 ListView에서 AddItem 함수를 호출했을 때 성공적으로 이 함수에 데이터를 전달할 수 있다.

저 On List Item Object Set 이벤트 노드는 바로 나타나있지는 않는다.
앞에서 User Object List Entry 인터페이스를 추가했을 때 이러한 이벤트들이 생겨났기 때문에 더블클릭으로 이벤트를 추가해 주면 된다.
테스트
이 일련의 과정이 성공적으로 작동되는지 확인하기 위해서는 어딘가에서 AddItem을 호출해보아야 한다.
void ACharacter_Base::JumpAction(const FInputActionInstance& _Instance)
{
Super::Jump();
// Test
// IvenItemData -> InventoryWidget
AUnreal_3thGameModeBase* pGameMode = Cast<AUnreal_3thGameModeBase>(UGameplayStatics::GetGameMode(GetWorld()));
UMainHUD_Base* pMainHUD = pGameMode->GetMainHUD();
UInventory_Base* pInvenWidget = pMainHUD->GetInventoryWidget();
UInvenItemData* pData = NewObject<UInvenItemData>();
pData->SetIconImgPath(TEXT("/Script/Engine.Texture2D'/Game/Texture/Viking_RPG_UI_5_0/Buttons/No_background_buttons/Flat_Icon_13_a.Flat_Icon_13_a'"));
pData->SetItemName(TEXT("롱 소드"));
pData->SetItemCount(1);
pInvenWidget->AddItem(pData);
}
그래서 캐릭터가 점프할 때마다 아이템을 하나씩 추가하는 테스트 코드를 작성하였다.
UGameplayStatics에서 게임모드를 가져오고
게임모드에서 MainHUD를 가져오고
MainHUD에서 Inventory를 가져오고
넣어 줄 데이터를 만들어 인벤토리 위젯의 AddItem을 호출하였다.
void UInventory_Base::AddItem(UObject* _ItemData)
{
m_ListView->AddItem(_ItemData);
}
(인벤토리 위젯에서 AddItem을 감싸서 호출할 수 있도록 구현해 놓은 부분)


정상적으로 아이템이 추가되는 것을 볼 수 있다.
참고로 여기서 아이템은 리스트의 칸 하나를 부르는 호칭일 뿐이지
인벤토리라서 이름을 아이템이라 붙인 것은 아니다.
'언리얼 > Assortrack UE5' 카테고리의 다른 글
| [언리얼] 학원 20일차: 인벤토리 끄기(UMG Input) (0) | 2023.09.22 |
|---|---|
| [언리얼] 학원 19일차: 아이템 획득, 인벤토리 매니저 (0) | 2023.09.21 |
| [언리얼] 학원 17일차: 버튼, RenderTexture (0) | 2023.09.19 |
| [언리얼] 학원 16일차: UMG: 언리얼 UI (0) | 2023.09.18 |
| [언리얼] 학원 15일차: AI Controller 플레이어 추적 (0) | 2023.09.15 |