ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Unreal] 언리얼 ListView 간단하게 알아보기
    쾌락없는 책임 (공부)/Unreal 2023. 3. 23. 13:35
    반응형

    개요

    아이템을 파밍 할 때 아이템에 픽업이 뜨는가, 사용자에게 근처에 있는 아이템 목록을 알려 주는가 등 여러 가지 방법이 있습니다. 저는 프로젝트에서 '플레이어 근처에 있는 아이템들의 목록을 보여주자' 라고 결정을 했고 이에 따라 이 목록을 위한 List View 가 필요했습니다. 다만 역시 알아보면 C++로 처리한 래퍼런스를 찾기 어려워 제가 만든 걸 공유하고자 이렇게 글을 쓰게 됩니다.

     

    - 간단 요약만 알고 싶다면 맨 아래로

     

    C++ 코드로 보는 ListView

    class UListView;
    
    UCLASS()
    class PROJECTFA_API UPickupItemList : public UUserWidget
    {
    	GENERATED_BODY()
    
    public:
    	
    	UPROPERTY(meta=(BindWidget))
    	TObjectPtr<UListView> NearbyItemList;
    	
    };

    일단 ListView의 코드는 이렇게 되어 있습니다. cpp 연동도 없는, 단순히 변수를 저장하기 위한 클래스입니다.

    void APlayableController::AddNearbyItem(UObject* Item)
    {
    	if(NearbyItemListNotValid())	return;
    	ProjectFAHUD->PickupItemList->NearbyItemList->AddItem(Item);
    }
    
    
    void APlayableController::DeleteNearbyItem(UObject* Item)
    {
    	if(NearbyItemListNotValid())	return;
    	ProjectFAHUD->PickupItemList->NearbyItemList->RemoveItem(Item);
    }

    이후 저의 경우 Controller에서 NearbyItemList에 AddItem, RemoveItem 을 통해 리스트에 아이템을 추가, 제거하는 작업을 해 줍니다. 이 함수는 플레이어 근처에 아이템이 들어오거나 나가면 불리게 되는 함수입니다.

     

    그런 다음 BP 에서 이 UI들을 만들어 줍니다.

    PickupItemList

    위 사진에서는 이미 List View 들의 요소들이 저장되어 있지만 요소를 만들어 줘야 합니다. 저의 경우 PickupItemListElement라고 이름 붙인 클래스를 만들었습니다.

    class UImage;
    class UTextBlock;
    
    UCLASS()
    class PROJECTFA_API UPickupItemListElement : public UUserWidget, public IUserObjectListEntry
    {
    	GENERATED_BODY()
    
    public:
    
    	virtual void NativeOnListItemObjectSet(UObject* ListItemObject) override;
    
    public:
    
    	UPROPERTY(meta=(BindWidget))
    	TObjectPtr<UImage> ItemImage;
    	UPROPERTY(meta=(BindWidget))
    	TObjectPtr<UTextBlock> ItemName;
    	
    };

    여기서 중요한 점은 IUserObjectListEntry 인터페이스를 상속해야 한다는 점입니다. 이 인터페이스를 받은 클래스만이 List View에 들어갈 수 있는 것입니다.

    이후 각 List View의 요소들 UI를 만들어 준 뒤

    이렇게 ListView 의 ListEntries > Entry Widget Class에 이 요소 UI를 넣어줍니다.

    이렇게 하면 ListView를 활용해 주변 아이템들을 보여줄 수 있습니다. 다만 디폴트 값인 Text Block으로 되어 있는 것을 볼 수 있습니다. 이때 IUserObjectListEntry를 상속받은 이유가 보이게 됩니다.

    void UPickupItemListElement::NativeOnListItemObjectSet(UObject* ListItemObject)
    {
    	IUserObjectListEntry::NativeOnListItemObjectSet(ListItemObject);
    	const APickupItem* Item = Cast<APickupItem>(ListItemObject);
    	if(Item == nullptr)	return;
    
    	ItemName->SetText(FText::FromString(Item->GetItemName()));
    }

    IUserObjectListEntry에서 상속받는 NativeOnListItemObjectSet 함수를 활용하면 됩니다. 이 함수는 ListView에서 해당 요소가 Set 될때 불리게 되는 함수로 이를 통해서 저는 UObject를 캐스팅, 이후 정보를 받아와 텍스트를 세팅했습니다.

    그러면 이렇게 아이템의 이름들을 볼 수 있게 됩니다!

     

     

    요약

    • List View에 들어가는 각 요소(칸)는 IUserObjectListEntry를 상속받은 클래스여야 한다!
    • IUserObjectListEntry를 상속받은 뒤 NativeOnListItemObjectSet 함수를 재정의하면 이 요소가 Set 될 때 행동을 정의 가능하다
    • List View는 TArray <TObjectPtr <UObject>> 로 이루어져 있습니다.
      • 때문에 TArray를 그대로 전달할 수도 있습니다.(이때는 SetListItems 함수 활용)
      • 내부적으로 TArray의 함수를 활용하므로 단순 Add, Remove를 해주면 다 처리를 해 줍니다.
      • 또한 각 요소가 UObject로 전달되기에 각 요소들의 NativeOnListItemObjectSet에서는 캐스팅을 해줘야 합니다.

     

     

    참고자료

     

    UListView

    A virtualized list that allows up to thousands of items to be displayed.

    docs.unrealengine.com

     

    반응형

    댓글

Designed by Tistory.