Unreal

C++을 사용한 언리얼엔진 인벤토리 시스템 Part.2

story98138 2026. 3. 10. 17:48

어제에 이어서 오늘은 인벤토리에 타일라인을 넣어보겠다.

*식자는 프로젝트 이름을 설정할 때 오타를 내서 IntentorySystemCpp로 만들어버렸지만 나중에 알아버려서 이는 굳이 수정하지 않겠다.

 

1.Character.h / cpp 파일

 

핵심 기능:

  • UInventoryComponent* InventoryComponent: 아이템 데이터를 저장하고 관리하는 두뇌 역할을 하는 컴포넌트이다.
  • InventoryWidgetClass & InventoryWidget:
    - Class는 화면에 띄울 UI 디자인(블루프린트)이 무엇인지 저장한다.
    - Widget은 실제로 생성되어 화면에 보여지고 있는 UI 객체이다.
  • ToggleInventory(): 인벤토리 키를 눌렀을 때 UI를 띄우거나 없애는 기능을 수행하는 함수이다.

 

#include "InventoryComponent.h" 도구를 추가하는 것을 잊지말자.

 

핵심기능:

  • ToggleInventory: 인벤토리 열고 닫기

void AIntentorySystemCppCharacter::ToggleInventory()
{
    if (InventoryWidget->IsInViewport()) { 
        // 1. 이미 화면에 떠 있다면? -> 닫기
        InventoryWidget->RemoveFromParent();
        GetPlayerController->SetShowMouseCursor(false); // 마우스 커서 숨기기
        GetPlayerController->SetInputMode(FInputModeGameOnly()); // 게임 조작만 가능하게
    }
    else {
        // 2. 화면에 없다면? -> 열기
        InventoryWidget->AddToViewport();
        GetPlayerController->SetShowMouseCursor(true); // 마우스 커서 보이기
        GetPlayerController->SetInputMode(FInputModeGameAndUI()); // 게임과 UI 모두 조작 가능하게
    }
}



2. InventoryComponent.h 파일

 

이 코드는 **"우리 게임의 인벤토리는 가로 X칸, 세로 Y칸이며 각 칸의 크기는 얼마이다"**라는 것을 정의하는 데이터 관리용 부품이다.

1. 인벤토리의 격자 구조 (Grid Layout)

  • int32 Columns: 인벤토리의 가로 칸 수. (예: 5칸)
  • int32 Rows: 인벤토리의 세로 줄 수. (예: 4줄)
  • float TileSize: 각 칸(타일)의 크기이다. UI에서 아이템이 그려질 때 각 격자가 차지할 픽셀 크기 등을 결정하는 데 사용된다.

2. 주요 함수 설명

  • UInventoryComponent(): 생성자이다. 위 변수들의 기본값(초기값)을 설정하는 곳이다.
  • BeginPlay(): 게임이 시작될 때 실행된다. 인벤토리에 초기 아이템을 지급하거나 데이터를 초기화하는 로직이 들어갈 자리이다.
  • TickComponent(): 매 프레임마다 실행되는 함수이다. 보통 인벤토리는 매 순간 계산할 필요가 없으므로, 최적화를 위해 나중에 기능을 끄기도 한다.

3. 코드의 특징 (UPROPERTY)
변수 위에 붙은 UPROPERTY(EditAnywhere, Category = ...)는 언리얼 엔진 에디터와의 연결 고리이다.

  • EditAnywhere: 코드를 다시 짜지 않아도, 언리얼 에디터의 상세(Details) 패널에서 가로/세로 칸 수와 타일 크기를 직접 숫자로 입력해 수정할 수 있게 해준다.
  • Category: 에디터 상에서 "IC Info | Inventory Columns" 처럼 깔끔하게 그룹화되어 보이도록 정리해주는 역할을 한다.

3. InventoryGridWidget.h 파일

 

1. UI 구성 요소 (BindWidget)

  • UCanvasPanel* Canvas: UI의 가장 바탕이 되는 도화지이다.
  • UBorder* GridBorder: 격자 외곽의 테두리나 배경색을 담당하는 박스이다.
  • UCanvasPanel* GridCanvasPanel: 실제 격자 선들이 그려질 전용 공간이다.

2. 격자 그리기를 위한 데이터

  • Columns, Rows, TileSize: 컴포넌트에서 받아온 정보를 그대로 사용해 몇 줄을 그릴지 결정한다.
  • StartX, StartY, EndX, EndY: 격자 선을 긋기 위한 시작 좌표와 끝 좌표를 저장하는 배열(TArray)이다.

3. 핵심 함수: 어떻게 화면에 그려지는가?

  • CreateLineSegments()
    - 이 함수는 실제 선을 긋기 전에 "어디에 선을 그어야 할지" 좌표를 계산하는 로직이 들어있다.
  • NativePaint() 
    - 매 프레임 혹은 UI가 업데이트될 때마다 저수준(Low-level) 드로잉을 수행한다.
    - 위에 계산된 좌표들을 이용해 DrawLine 같은 명령어로 실제 화면에 격자 선을 "직접 그린다."
    - 이미지를 한 장 크게 깔아두는 방식보다 메모리가 절약되고, 가로/세로 칸 수를 실시간으로 바꿔도 즉각 반영된다는 장점이 있다.

4. InventoryGridWidget.cpp 파일

 

1. NativeConstruct: 데이터 동기화 및 크기 설정

  • 캐릭터 연결: 현재 플레이어가 조종하는 캐릭터와 그 안에 있는 InventoryComponent를 찾아온다.
  • 정보 복사: 컴포넌트에 설정된 가로(Columns), 세로(Rows), 타일 크기(TileSize) 정보를 위젯 변수로 가져온다.
  • 크기 조절: Columns * TileSize와 Rows * TileSize를 계산해 인벤토리 배경 박스(GridBorder)의 크기를 자동으로 맞춘다. 가방 칸수가 늘어나면 UI 크기도 자동으로 커지게 된다.

2. CreateLineSegments: 격자 선의 좌표 계산

  • 세로선 계산 (for 루프): 0부터 가로 칸 수까지 반복하며 선의 X 좌표를 결정한다.
    - 예: 타일 크기가 50이면, X 좌표 0, 50, 100... 지점에 세로선을 긋기 위한 데이터를 만든다.
  • 가로선 계산 (for 루프): 0부터 세로 칸 수까지 반복하며 선의 Y 좌표를 결정한다.
  • 이렇게 계산된 좌표들은 StartX, EndX 등의 배열에 저장되어 다음 단계에서 사용된다.

3. NativePaint: 실시간 선 그리기

  • FPaintContext: 언리얼 엔진의 드로잉 도구 상자이다.
  • 좌표 보정: TopLeftCorner 변수를 통해 배경 박스의 왼쪽 위 위치를 기준으로 선이 올바른 곳에 그려지도록 보정한다.
  • DrawLine: UWidgetBlueprintLibrary::DrawLine 함수를 호출한다.
    - 반복문을 돌며 앞서 계산한 좌표를 연결해 **격자 무늬(Grid)**를 완성이다.

5. 테스트하기

내 캐릭터 블루프린트를 열어 실제로 Inventory Component 가 있는지 확인한다.


Inventory Component를 클릭하고 디테일 창의 IC Info란에서 세로칸 수, 가로칸 수, 타일사이즈를 조정한다.

컴파일 후 세이브***

 

실행 후 I key를 눌렀을 때 잘 작동하는지 확인한다.

 


6. 마무리

이것으로 C++을 사용한 언리얼엔진 인벤토리 시스템 Part.2를 마치겠다. 
Part.3에서는 지금까지 만든 인벤토리 배열에 아이템을 추가하는 로직을 짜보겠다.