[UE5] GridInventory System (5) - 인벤토리에 아이템이미지 추가하기

vector·2025년 12월 12일

UE5 C++ GridInventory

목록 보기
5/7
post-thumbnail

이전에 아이템과 충돌 시 인벤토리에 넣을수 있는지를 판별한 다음, 가능하다면 사라지지도록 만들어봤다.
이번에는 아이템을 인벤토리에 넣고 인벤토리에 Icon이 나오도록 해보자

인벤토리 토글 수정

그 전에 인벤토리를 I키를 누르면 끄고 켜고 했지만, 일단 켜두고 Visible만 껐다 켰다하는 형식으로 수정하고 진행하자.

void AGridInventoryCharacter::BeginPlay()
{
	Super::BeginPlay();

	// PlayerController 가져오기
	PC = UGameplayStatics::GetPlayerController(GetWorld(), 0);

	if (PC)
	{
		if (InventoryWidgetClass)
		{
			InventoryWidget = CreateWidget(GetWorld(), InventoryWidgetClass);
			InventoryWidget->SetOwningPlayer(PC);
			InventoryWidget->AddToViewport();
			InventoryWidget->SetVisibility(ESlateVisibility::Collapsed);
		}
	}
}

void AGridInventoryCharacter::ToggleInventory()
{
	if (InventoryWidget->GetVisibility() == ESlateVisibility::Collapsed)
	{
		InventoryWidget->SetVisibility(ESlateVisibility::Visible);
		PC->SetInputMode(FInputModeGameAndUI());
		PC->SetShowMouseCursor(true);
	}
	else
	{
		InventoryWidget->SetVisibility(ESlateVisibility::Collapsed);
		PC->SetInputMode(FInputModeGameOnly());
		PC->SetShowMouseCursor(false);
	}
}

아이템 Icon 만들기

  • ItemBase에서 Icon 변수 추가하기
protected:
	UPROPERTY(EditAnywhere, Category = "Item Info | Icon")
	UMaterialInterface* Icon;
  • 아이콘 리소스
    https://drive.google.com/drive/folders/1-_0otpQBbicKisdJxRiyxN-iXFvCrWJo

  • 에디터에 추가하고 머터리얼로 만들어주자

  • 먼저 Texture 우클릭 후 - AssetAction - Edit Selection in Property Material 선택

  • 전체 선택 후 Texture Group을 UI로 변경

  • 베이스 머터리얼 생성 (M_IconBase)
    - Texture와 회전된 Texture까지 같이 설정해주기

  • 각 아이템마다 머터리얼 인스턴스 생성 후 액터에 넣어주기

인벤토리에 아이템 추가하기

  • GridInventoryCharacter에서 ItemWidgetClassItemWidget변수 추가하고, ItemWidgetClass는 에디터에서 추가해주기

  • 아이템을 추가할때 InventoryComponent에서 아이템을 추가하기 위한 bool값 변수 AddedItem을 추가하고, AddItemAt()에서 마지막에 true값을 넣기

// InventoryComponent.h
public:
	bool AddedItem = false;
    
    
// InventoryComponent.cpp
void UInventoryComponent::AddItemAt(AItemBase* ItemToAdd, int32 TopLeftIndex)
{
	FIntPoint dimensions = ItemToAdd->GetDimension();
	FIntPoint tile = IndexToTile(TopLeftIndex);	// 좌상단의 타일값

	for (int32 i = tile.X; i <= tile.X + dimensions.X - 1; i++)
	{
		for (int32 j = tile.Y; j <= tile.Y + dimensions.Y - 1; j++)
		{
			Items[TileToIndex(FIntPoint(i, j))] = ItemToAdd;
		}
	}

	AddedItem = true;
}    
  • AddedItem이 true가 되면 InventoryGridWidget에서 아이템이미지를 추가해주는 코드를 추가하자 -> InventoryComponent::TickComponent()에서 호출
void UInventoryComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
{
	Super::TickComponent(DeltaTime, TickType, ThisTickFunction);

	if (AddedItem)
	{
		InventoryGridWidgetReference->Refresh();
		AddedItem = false;
	}
}

InventoryGridWidget::Refresh()

  • 아이템이 추가될때 호출되는 함수
  • ItemBase의 배열인 keys선언하고, InventoryComponentAllItems의 Key값을 keys 변수에 넣어주자
  • 만약에 ItemWidgetClass가 있다면, ItemWidget을 생성해주자.
  • keys for문을 돌면서 인벤토리에 추가되어 있는 아이템의 위치값을 가져와서,
  • GridCanvasPanel에 사이즈는 자동으로, 위치는 잡아준 위치로ItemWidget을 추가해준다.
void UInventoryGridWidget::Refresh()
{
	TArray<AItemBase*> keys;
	InventoryComponent->GetAllItems().GetKeys(keys);

	if (CharacterReference->GetItemWidgetClass())
	{
		CharacterReference->CreateItemWidget();

		for (AItemBase* AddedItems : keys)
		{
			// ItemWidget의 소유플레이어를 InventoryGrid와 동일하게 셋팅
			CharacterReference->GetItemWidget()->SetOwningPlayer(GetOwningPlayer());

			int32 x = InventoryComponent->GetAllItems()[AddedItems].X * InventoryComponent->TileSize;
			int32 y = InventoryComponent->GetAllItems()[AddedItems].Y * InventoryComponent->TileSize;

			PanelSlot = GridCanvasPanel->AddChild(CharacterReference->GetItemWidget());
			Cast<UCanvasPanelSlot>(PanelSlot)->SetAutoSize(true);
			Cast<UCanvasPanelSlot>(PanelSlot)->SetPosition(FVector2D(x, y));
		}
	}
}

ItemWidget::Refresh()

  • 아이템이 추가되고, ItemWidget이 생성될때 호출 -> NativeConstruct에서 호출
  • Refresh(CharacterReference->ItemToAdd); : ItemToAdd는 플레이어와 충돌한 액터이다. (BeginOverlap에서 설정)
  • 가져온 아이템의 IconItemImage에 추가하기
  • 아이템의 Dimension으로 icon의 사이즈 값을 설정하고,
  • 사이즈 값으로 SizeBoxItemImage의 크기 설정하기
void UItemWidget::NativeConstruct()
{
	Super::NativeConstruct();

	CharacterReference = Cast<AGridInventoryCharacter>(UGameplayStatics::GetPlayerCharacter(GetWorld(), 0));

	if (CharacterReference)
	{
		Refresh(CharacterReference->ItemToAdd);
	}
}

void UItemWidget::Refresh(AActor* ItemToAdd)
{
	AItemBase* item = Cast<AItemBase>(ItemToAdd);

	ItemImage->SetBrushFromMaterial(item->GetIcon());
	
	// 인벤토리에 보이는 icon 사이즈 값 설정
	Size = FVector2D(item->GetDimension().X * CharacterReference->GetInventoryComponent()->TileSize, 
					item->GetDimension().Y * CharacterReference->GetInventoryComponent()->TileSize);

	// 사이즈박스 값 설정
	BackgroundSizeBox->SetWidthOverride(Size.X);	// 가로
	BackgroundSizeBox->SetHeightOverride(Size.Y);	// 세로

	// 이미지 크기 설정
	UCanvasPanelSlot* imageAsCanvasSlot = UWidgetLayoutLibrary::SlotAsCanvasSlot(ItemImage);
	imageAsCanvasSlot->SetSize(Size);
}

결과

  • 마지막 빨간색은 4x2 크기여서 추가x

참고 영상

https://www.youtube.com/watch?v=3OAlwUmOD7s

profile
게임 클라이언트 프로그래머 준비중 (공부 및 기록용)

0개의 댓글