인벤토리 시스템 만들기
Inventory Slot 만들기

public:
UMyInventorySlotWidget(const FObjectInitializer& ObjectInitializer = FObjectInitializer::Get());
protected:
virtual void NativeConstruct() override;
public:
UPROPERTY(meta = (BindWidget))
TObjectPtr<USizeBox> SizeBox_Root;
UPROPERTY(meta = (BindWidget))
TObjectPtr<UImage> Image_Slot;
void UMyInventorySlotWidget::NativeConstruct()
{
Super::NativeConstruct();
SizeBox_Root->SetWidthOverride(50);
SizeBox_Root->SetHeightOverride(50);
}
- 인벤토리의 한 칸을 의미한다.
- 이미지는 추후 아이템 아이콘으로 교체된다.
Inventory Slots 만들기

- GridPanel_Slots에서는 Inventory slot을 여러개 들고 있음
public:
UMyInventorySlotsWidget(const FObjectInitializer& ObjectInitializer = FObjectInitializer::Get());
protected:
virtual void NativeConstruct() override;
protected:
UPROPERTY()
TSubclassOf<UMyInventorySlotWidget> SlotWidgetClass;
UPROPERTY()
TArray<TObjectPtr<UMyInventorySlotWidget>> SlotWidgets;
UPROPERTY(meta = (BindWidget))
TObjectPtr<UUniformGridPanel> GridPanel_Slots;
private:
UPROPERTY(meta = (BindWidget))
TObjectPtr<UCanvasPanel> CanvasPanel_Entries;
private:
const int X_COUNT = 10;
const int Y_COUNT = 5;
- UMyInventorySlotWidget으로부터 파생된 클래스 자체를 들고있다.
- 동적 생성한 인벤토리 슬롯을 TArray로 들고있는다.
- GridPanel에 인벤토리 슬롯을 동적생성한다.
UMyInventorySlotsWidget::UMyInventorySlotsWidget(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
{
ConstructorHelpers::FClassFinder<UMyInventorySlotWidget> FindSlotWidgetClass(TEXT("/Script/UMGEditor.WidgetBlueprint'/Game/UI/Item/Inventory/WBP_InventorySlot.WBP_InventorySlot_C'"));
if (FindSlotWidgetClass.Succeeded())
{
SlotWidgetClass = FindSlotWidgetClass.Class;
}
}
void UMyInventorySlotsWidget::NativeConstruct()
{
Super::NativeConstruct();
SlotWidgets.SetNum(X_COUNT * Y_COUNT);
for (int32 y = 0; y < Y_COUNT; y++)
{
for (int32 x = 0; x < X_COUNT; x++)
{
int32 index = y * X_COUNT + x;
UMyInventorySlotWidget* SlotWidget = CreateWidget<UMyInventorySlotWidget>(GetOwningPlayer(), SlotWidgetClass);
SlotWidgets[index] = SlotWidget;
GridPanel_Slots->AddChildToUniformGrid(SlotWidget, y, x);
}
}
}
- 생성자에서 InventorySlot Widget 클래스의 정보를 FClassFinder를 통해 찾아 넣어준다.
- 5x10 크기의 격자로 위젯을 생성해서 그리드 패널의 하위에 추가한다.
Item Drag & Drop 시스템 만들기
Object를 상속받아 Itme 클래스 만들기
- 언리얼에서 자동으로 할당해주는 메모리를 사용하기 위해 Object를 상속
UCLASS(BlueprintType)
class My_API UMyItemInstance : public UObject
{
GENERATED_BODY()
public:
UMyItemInstance(const FObjectInitializer& ObjectInitializer = FObjectInitializer::Get());
public:
void Init(int32 InItemID);
public:
UPROPERTY()
int32 ItemID = 0;
UPROPERTY()
EItemRarity ItemRarity = EItemRarity::Junk;
};
void UMyItemInstance::Init(int32 InItemID)
{
if (InItemID <= 0)
return;
ItemID = InItemID;
ItemRarity = EItemRarity::Common;
}
UENUM(BlueprintType)
enum class EItemRarity : uint8
{
Junk,
Poor,
Common,
Uncommon,
Rare,
Epic,
Legendary,
Unique,
Count UMETA(Hidden)
};
- Count는 개수를 셀 때 사용하고 UMETA(Hidden) 키워드를 이용해 숨길 수 있다
Subsystem을 상속받아 인벤토리 만들기
public:
virtual void Initialize(FSubsystemCollectionBase& Collection) override;
virtual void Deinitialize() override;
void AddDefaultItems();
const TArray<TObjectPtr<UMyItemInstance>>& GetItems() { return Items; }
protected:
UPROPERTY()
TArray<TObjectPtr<UMyItemInstance>> Items;
void UMyInventorySubsystem::AddDefaultItems()
{
TObjectPtr<UMyItemInstance> Item = NewObject<UMyItemInstance>();
Item->Init(100);
Items.Add(Item);
}
- WorldSubsystem을 상속받았기 때문에 World의 생명주기를 따라간다.
- 아이템의 원본 데이터는 서브시스템이 가지고 있고 UI에서 아이템을 전달받아 사용한다.
GameMode의 초기화 부분에 Inventory Subsystem 초기화하기
public:
virtual void InitGame(const FString& MapName, const FString& Options, FString& ErrorMessage) override;
void AMyGameMode::InitGame(const FString& MapName, const FString& Options, FString& ErrorMessage)
{
Super::InitGame(MapName, Options, ErrorMessage);
UMyInventorySubsystem* Inventory = Cast<UMyInventorySubsystem>(USubsystemBlueprintLibrary::GetWorldSubsystem(this, UMyInventorySubsystem::StaticClass()));
if (Inventory)
{
Inventory->AddDefaultItems();
}
}
- 게임이 시작하면서 실행되기 때문에 Subsystem을 초기화 하기 좋다
- GameInstance Subsystem이라면 GameInstance에서 받아오면 되지만 World의 경우 USubsystemBlueprintLibarary에서 받아올 수 있다