
타르코프나 디아블로에서 쉽게 찾아볼 수 있는 그리드 형태의 인벤토리를 구현해보았다.
인벤토리 내에서 R키를 이용해 회전하거나, 드래깅하여 아이템을 줍고 버리는 기능도 마찬가지로 구현되어있다.


유저 위젯 블루프린트와 Actor Component를 상속받는 Inventory Component를 생성해준다.

Line과 Tile을 담아줄 Structure와 Slate Brush를 생성한다.


Line 및 Tile Structure에 넣어줄 데이터들
Slate Brush는 생성만 해주면 된다.

인벤토리를 열때 사용할 키 바인딩도 마찬가지로 생성해주도록 하자.
(Enhanced Input System을 사용해서 'I' 키를 할당해주었다.)

플레이어 Begin Play에 Create Widget으로 미리 만들어둔 WBP_Inventory를 할당해주고 변수로 빼주었다.

인벤토리 키에 Focus 설정을 해주고 변수로 뺀 인벤토리 위젯을 연결해주고,

ShowMouseCursor를 이용해서 커서가 보이거나 보이지 않게 해주었다.

WBP_Inventory를 꾸며주도록 한다.
Canvas Panel에 Border를 넣고 Brush Color의 Alpha 값을 0.2로 해서 배경을 넣어주고
BackGround Blur를 통해 약간의 Blur 값을 넣어주면 꽤나 그럴싸해진다. (여기서는 Blur Strength를 2.0으로 세팅해주었다.)
그리고 미리 만들어둔 실제 인벤토리를 표현할 WBP_InventoryGrid를 우측에 배치해주었다.
(Size To Content 기능을 체크해서 이후 만들게 될 WBP_InventoryGrid의 사이즈에 맞춰 유동적으로 변할 수 있게 했다.)
(위 이미지에서는 이미 만들어두었기에 표시가 된 모습)
이제 WBP_InventoryGrid를 만들어보자.

마찬가지로 Canvas Panel 아래에 Border를 넣어주고 적당한 사이즈를 정해주도록 하자.
여기선 (150, 600), Padding 값 0, Brush color (0,0,0,0.25) 로 설정 했다.
보더 안에 Canvas Panel를 하나 더 넣어주고 Panel_Grid로 명명했다.
이렇게 만들게 되면 상단의 인벤토리 이미지와 같이 보이게 될 것이다.
이제 Inventory Grid의 그래프탭으로 넘어가서 기능을 구현해보록 하자.

인벤토리 그리드에 Initialize 함수를 생성하고
Input으로 Inventory Component와 TileSize를 받아오도록 했다.

Input으로 받아오는 두 개의 값을 변수로 승격해주었다.
Inventory Component로 돌아가서 변수를 선언하고 오도록 한다.


행과 열의 data를 담을 Columns 와 Rows를 선언하고, 해당 옵션들을 켜주도록 하자.
다시 WBP_InventoryGrid로 돌아와서 해당 행렬을 실제 사이즈를 맞추는데 사용하면

위와 같이 Component에서 설정한 행렬의 값을 TileSize와 곱해서 BorderGrid의 SetSize 노드를 이용해 실 Size를 정립한다.
WBP_InventoryGrid 인벤토리 내에 Line을 그려줄 새로운 함수를 만들어보자.


행과 열만큼의 라인이 필요하니 For Loop 노드를 이용해 행렬 값 만큼 반복하게 해주고

각 행렬값과 TileSize를 곱하여 X,Y 값을 구해서 Local 변수로 저장해주고
구하게 될 Line 값을 저장해줄 처음 만들었던 S_Line을 상속받는 Line Array를 선언해서
여기서 얻게된 Local X,Y 값을 각 각 저장해주었다.

Function Override에서 On Paint를 오버라이딩해서 함수를 하나 만들어준다.
해당 함수는 우리가 위젯에 Draw Line 노드를 이용해 실제 선을 그릴 수 있도록 해준다.

On Paint 내부에서 시퀀서를 이용해 앞으로 할 작업을 분리해주고,
방금 구한 Lines의 Data를 이용해 선을 그려보도록 하자.
Lines의 Data를 순회할 수 있게 For Each Loop 노드를 이용해서

다음과 같이 우리가 볼 수 있는 실제 선(Line)을 그려줄 수 있다.

다른 시퀀서에는 이후에 할 작업(아이템을 집고 내려놓을 때 위치를 표기할 Line)을 기술해두고 다른 작업으로 넘어가자.

이후 시퀀서에 Return node를 연결하고 우선 마무리하도록 한다.
이제껏 작업한 함수를 실제로 호출하도록 해야하므로,
Initialize 함수로 돌아와서 Create Line Segement를 연결해준다.

WBP_Inventory로 돌아가서 InventoryComponent를 담은 변수를 생성해주고


내친김에 TileSize도 전달해줘야 하니 같이 만들어주도록 하자.
이벤트 그래프에서 Event On Initialize 이벤트를 호출하고 InventoryGrid에서 만든 Initialize 함수를 호출하며 값을 전달한다.

하지만 여기서 해당 함수만 호출하게되면 동작을 하지 않는데,
Initialize 이벤트는 게임 실행 후 다음 프레임까지 실제로 데이터를 제대로 전달하지 못한다.(아마도 언리얼 엔진 버그?)
그렇기 때문에 0.0 초의 딜레이를 걸어주면(Initialize 직후 프레임)
문제 없이 데이터를 전달하며 제대로 동작하게 된다.
궁금하면 딜레이 노드를 제거 후 직접 테스트 해보도록 하자.
이제 플레이어 케릭터로 돌아가서 이벤트 그래프에서 Inventory Widget에 전달해줄 TileSize와 Inventory Component를 연결해주면..


여기까지 문제 없이 해왔다면,

다음과 같이 내가 할당한 인벤토리 키를 누르면 다음과 같이 인벤토리 위젯을 볼 수 있다!
만약 InventoryGrid가 보이지 않는다면, 케릭터에 추가한 InventoryComponent에서 행렬의 크기를 정해주었는지 확인 해보도록 하자.
