인벤토리를 구현해보겠습니다
1인 개발이다보니 기획도 스스로 해야했습니다 (어쩔수있나요)
인벤토리 초기 구상도입니다
인벤토리 구상도

인벤토리 기능
인벤토리의 현재 기능은 이와 같습니다
- 위쪽 상단바를 마우스 드래그앤드롭으로 움직일수 있습니다
- InventoryComponent에서 설정된 InvenCount 만큼 인벤 슬롯이 생성됩니다
- 인벤토리갯수가 창을 넘어갈경우 스크롤 박스로 마우스 휠 업다운으로 움직일수있습니다
- 인벤토리 끝부분을 잡으면 크기가 리사이징이 가능합니다
- 아이템을 드래그앤드롭 하여 옮길수 있습니다
- 재화는 총 2가지 종류이며 인벤토리에서 갯수만큼 보여집니다
- 아이템을 드래그앤드롭하여 파란부분에 넣으면 아이템은 사라집니다
- 우측하단 주황색버튼을 누르면 아이템은 가나다 순으로 정렬됩니다
- 우측 상단 X키를 누르면 인벤토리UI는 숨겨집니다
- 아이템을 먹으면 인벤토리로 들어와지고 마우스 우클릭을 통해 아이템을 사용할수있습니다
- 퀵슬롯과 연동하여 드래그앤드롭하여 아이템을 움직일수 있습니다
역시 인벤토리! 구현할게 산더미만큼 많군요!
인벤토리가 확실히 구현난이도에서 어려운거같습니다
현재까지 구현한 내용
- 위쪽 상단바를 마우스 드래그앤드롭으로 움직일수 있습니다
- InventoryComponent에서 설정된 InvenCount 만큼 인벤 슬롯이 생성됩니다
- 인벤토리갯수가 창을 넘어갈경우 스크롤 박스로 마우스 휠 업다운으로 움직일수있습니다
- 인벤토리 끝부분을 잡으면 크기가 리사이징이 가능합니다
- 재화는 총 2가지 종류이며 인벤토리에서 갯수만큼 보여집니다
- 우측 상단 X키를 누르면 인벤토리UI는 숨겨집니다
구현방식
현재 생성된 클래스는 이와 같습니다
| UInventoryWidget | 인벤토리 전체 UI를 담당하는 위젯 클래스 |
| USlotWidget | 인벤토리 안의 한 칸 슬롯을 담당하는 위젯 클래스 |
| UInventoryComponent | 캐릭터에 붙은 컴포넌트로 실제 아이템 데이터와 슬롯 수 등 인벤토리에 대한 값들 관리 |
먼저 사용할 인벤토리 위젯을 만들어주었습니다
인벤토리에서 드래그 하여 인벤토리를 움직여주거나 리사이징 하는 자료가 인터넷에 블루프린트 내용밖에없어서
C++로 구현하니 처음부터 직접 구현하게되니 힘들었습니다
언리얼에서 UI위젯은 마우스 클릭이나 이동 같은 이벤트를 받을 수 있는 콜백함수를 제공합니다
virtual FReply NativeOnMouseButtonDown(const FGeometry& inGeometry, const FPointerEvent& inMouseEvent) override;
virtual FReply NativeOnMouseButtonUp(const FGeometry& inGeometry, const FPointerEvent& inMouseEvent) override;
virtual FReply NativeOnMouseMove(const FGeometry& inGeometry, const FPointerEvent& inMouseEvent) override;
NativeOnMouseButtonDown : 마우스 버튼을 누를때 호출됩니다
NativeOnMouseButtonUp : 마우스 버튼을 떼는 순간 호출됩니다
NativeOnMouseMove : 마우스가 위젯 영역 안에서 움직일 떄 매 프레임 호출됩니다
해당 콜백함수로 드래그 기능을 구현할수 있었습니다
위젯내에 각 보더를 붙혀서 보더를 클릭하면 전체 위젯을 키우거나 줄이거나 하였습니다
(전체 코드는 코드개인보관함에 따로 비밀번호를 걸어 올려두겠습니다 구독하신뒤 비밀댓글 달아주시면 비밀번호 제공해드립니다)
2025.11.22 - [개인 코테 & 스타디 <비공개>/코드 개인보관함] - 인벤토리 크기 리사이징 & 드래그앤드롭 전체코드
인벤토리 크기 리사이징 & 드래그앤드롭 전체코드
lucodev.tistory.com
NativeOnMouseMove 함수입니다
드래그 하여 인벤토리를 움직이는 기능과 리사이징 기능을 추가하여주었습니다
FReply UInventoryWidget::NativeOnMouseMove(const FGeometry& inGeometry, const FPointerEvent& inMouseEvent)
{
if (bIsDragging && OutterBox)
{
if (UCanvasPanelSlot* canvasSlot = Cast<UCanvasPanelSlot>(OutterBox->Slot))
{
FVector2D localMousePos = inGeometry.AbsoluteToLocal(inMouseEvent.GetScreenSpacePosition());
FVector2D nowNewPos = localMousePos - dragOffset;
canvasSlot->SetPosition(nowNewPos);
}
return FReply::Handled();
}
if (bIsResizing && currentResizeBorder && OutterBox)
{
if (UCanvasPanelSlot* canvasSlot = Cast<UCanvasPanelSlot>(OutterBox->Slot))
{
FVector2D mousePos = inGeometry.AbsoluteToLocal(inMouseEvent.GetScreenSpacePosition());
FVector2D delta = mousePos - startMousePos;
FVector2D newPos = startPos;
FVector2D newSize = startSize;
//왼쪽드래그보더
if (currentResizeBorder == Border_ML)
{
float newWidth = FMath::Max(minWidth, startSize.X - delta.X);
newPos.X = startPos.X + (startSize.X - newWidth);
newSize.X = newWidth;
}
//오른쪽 드래그보더
else if (currentResizeBorder == Border_MR)
{
newSize.X = FMath::Max(minWidth, startSize.X + delta.X);
}
//왼쪽하단 드래그보더
else if (currentResizeBorder == Border_BL)
{
float newWidth = FMath::Max(minWidth, startSize.X - delta.X);
newPos.X = startPos.X + (startSize.X - newWidth);
newSize.X = newWidth;
newSize.Y = FMath::Max(minHeight, startSize.Y + delta.Y);
}
//오른쪽하단 드래그보더
else if (currentResizeBorder == Border_BR)
{
newSize.X = FMath::Max(minWidth, startSize.X + delta.X);
newSize.Y = FMath::Max(minHeight, startSize.Y + delta.Y);
}
//하단 드래그보더
else if (currentResizeBorder == Border_BC)
{
newSize.Y = FMath::Max(minHeight, startSize.Y + delta.Y);
}
canvasSlot->SetPosition(newPos);
canvasSlot->SetSize(newSize);
}
return FReply::Handled();
}
return Super::NativeOnMouseMove(inGeometry, inMouseEvent);
}
위젯을 제작해주었습니다

WrapBox와 그리드패널 스크롤박스를 사용하여 제작하였습니다
인벤토리슬롯 위젯또한 제작해주었습니다

InventoryComponent내에서 Getter 함수로 인벤토리 갯수를 Return 해주었습니다
int32 UInventoryComponent::GetSlotCount()
{
return baseInvenSlotCount;
}
해당 갯수만큼 WrapBox내에 추가해주었습니다
void UInventoryWidget::InitSlot()
{
WrapBox_Inven->ClearChildren();
int32 slotCount = inventoryComp->GetSlotCount();
for (int32 i = 0; i < slotCount; i++)
{
if (!slotWidgetClass)
continue;
USlotWidget* slot = CreateWidget<USlotWidget>(this, slotWidgetClass);
WrapBox_Inven->AddChild(slot);
}
}
결과
인벤토리가 원하는 슬롯 갯수만큼 추가가 되며 상단바를 잡고 이동시킬수있으며
원하는대로 모서리부분을 잡고 리사이징이 가능해졌습니다


'Unreal 프로젝트 다이어리 > 두번째 프로젝트' 카테고리의 다른 글
| Unreal - 인벤토리(3) (드래그 앤 드롭) (0) | 2025.11.25 |
|---|---|
| Unreal - 인벤토리(2) ( 아이템 추가하기 ) (0) | 2025.11.23 |
| Unreal - UI (HpWidget, PostureWidget) (0) | 2025.11.21 |
| Unreal - StatComponent (0) | 2025.11.21 |
| Unreal - 상호작용(사다리 타기) (0) | 2025.11.15 |