
언리얼 엔진에서 아이콘 제작은 실제 3D Actor를 이용해 야매(?)로 만드는 방법도 있고,
포토샵이나 기타 이미지 편집 툴을 이용해서 제작하는 방법 등 다양한 방법이 있다.
이후에 아이템을 추가하거나 아이콘이 필요하다면 해당 부분을 찾아보면 쉽게 접할 수 있을 것이다.

추가한 이미지의 Texture Group과 Compression Settings를 다음과 같이 UI로 변경해주도록 한다.

배치 될 아이템을 담아줄 Actor - BP_Item 과 Object - BP_ItemObject 를 생성하자.

Create Child Blueprint로 튜토리얼에서 사용할 BP_AK74, grenade, knife를 만들어주었다.

BP_Item 내부에 StaticMesh를 추가하고 Sphere Collision도 추가해준다.
이전에 BP_ItemObject를 만들었던 이유는 아이템의 이미지(회전하는 이미지도 포함)와 인벤토리에서의 공간 Data를 들고 있기 위함이다.

그러므로 해당 아이템 오브젝트 래퍼런스를 변수 다음과 같이 선언해준다.

BP_Item 이벤트 그래프의 BeginPlay에서 ItemObject가 유효한지 체크해주도록 하고
GetDefaultItemObject 함수를 생성해준다.

즉 해당 함수는 ItemObject의 기본값을 반환하는 역할을 한다. (C++에서의 Getter 와 같은 역할)

이제 Beginplay에서 해당 함수를 호출하고 변수로 선언한 ItemObject에 할당해준다.

Sphere Collision의 Overlap 이벤트를 설정해주었다.
해당 BP_Item에 플레이어 캐릭터가 오버랩되면 발생할 이벤트를 설정해 줄 예정이다.

InventoryComponent로 돌아가서 TryAddItem 함수를 만들어주도록 한다.
Input에는 ItemObject를 받아오고, Output에는 실제 아이템 정보가 추가됐는지 안됐는지 판별할 Boolean을 설정하고
다시 BP_Item으로 돌아가서 해당 함수를 호출하도록 했다.

이제 TryAddItem 함수에 실제로 아이템을 인벤토리에 추가할 수 있도록 하는 기능을 만들어보자.

InventoryComponent에서 Items(인벤토리에 존재하게 될 아이템 정보)를 담을 ItemObject (Array)를 선언해주었다.

우선, 인벤토리에 해당 아이템 오브젝트를 추가할 때 인벤토리에 여유 공간이 있는지 확인해야 한다.
이를 위한 함수를 선언해보자.

IsRoomAvailable 함수를 선언하고 상단의 필요한 파라미터를 설정해주도록 하자.
당연히 아이템의 정보를 전달해줘야 하므로 ItemObject를 Input에 넣고
TopLeftIndex(아이템을 추가할 공간 제일 좌측 상단 공간)에 대한 Data도 전달해줄 수 있도록 했다.
성공 여부를 반환해야 하므로 Output에 Boolean을 추가한다.

여기서 간단한 Is Tile Valid 매크로를 만들어서 해당 Index가 유효한지 체크를 할 것이다.


여기서 Index는 개발자가 입력할 아이템의 사이즈값인데 우리는 아직 해당 데이터를 선언해주지 않았다.
BP_ItemObject로 가서 해당 변수와 Getter 함수를 선언해주자.



다시 InventoryComponent로 돌아와서 해당 함수와 변수를 이용해서 For Each Index매크로 내에서
실제 인벤토리 Index에 추가할 공간이 있는지 확인하는 절차를 거치고 난 뒤 각 X,Y 축 TileSize를 반환한다.

자 이제 IsTileValid 매크로를 통해 Index가 유효한지까지 성공했다면, 해당 Index를 가져오도록 한다.

이를 위해서 GetItemIndex 함수를 만들어주었다. 해당 함수는 주어진 인덱스에 추가된 아이템이 있는지 확인한다.

Tile To Index 함수를 만들어준다. 위에 기술했다시피 이는 아이템의 Tilesize를 1차원 Index값으로 변환시켜주는 함수이다.
이제 isRoomAvailable 함수로 돌아와 이들을 조립해보자

Index에 아이템이 존재하고, ItemObject가 유효하다면, 해당 함수(IsRoomAvailable)는 시퀀서2까지 넘어와서 true를 반환하게 된다.
즉 이제 우리는 아이템이 Index에 존재하는지,
ItemOjbect가 존재하는지 유효성 검사까지 해주고 인벤토리에 충분한 공간이 있는지까지 확인하는 편리한 기능의 함수를 갖게 되었다.
이제 원래 목적인 TryAddItem 함수로 돌아가서..

Item의 내부를 순회해서 충분한 공간이 있는지 확인하고, 만약 여유가 된다면. 해당 배열에 아이템을 실제로 추가해야 한다.

TileSize와 ItemObject를 가져와서 TileToSize 매크로를 이용해 아이템의 2차원 좌표값을 변환시키고 ItemObject 배열에 Set Array Element 노드를 이용해 추가해준다.
해당 작업이 성공하면 IsDirty Boolean을 True값으로 반환해주도록 한다. (무언가 바뀌었다는 것을 UI 혹은 다른 무언가에 알리기 위함)


충분한 공간이있으면, 해당 아이템을 배열에 추가하고 true를 반환한다.
아니라면 false를 반환한다.
이제 우리는 Inventory Component에서 아이템이 유효한지 검사하고 실제로 인벤토리 배열에 추가하는 기능을 구현해냈다.
잊어먹기전에 아이템 배열을 초기화 하는 로직을 추가하고 가도록 하자.

InventoryComponent Beginplay에서 ItemObject를 Resize 해주었다.
이제 기능 테스트를 위해서 몇 가지 단계를 거칠 예정이다.
이전에 추가했던 AK-47 BP_Item을 주울수 있도록 만들어보자.

그 이전에 우리는 BP_Item 전달해야 할 몇 가지 데이터를 설정해줘야 하는데,
BP_ItemOjbect에서 몇 가지 변수를 선언하고 넘어가도록 하자.

BP_Item Class와, Icon Image를 표기할 Material Instance를 상속받은 Icon 변수를 선언해주었다.
여기서 Class 참조를 담는 이유는 실제 변화하게 될 아이템 클래스(여기선 AK-47)를 추적하기 위함이다.
Rotate 변수는 이후에 아이템을 돌리는 기능을 만들 때 추가로 사용 할 것이다.

이제 AK-47의 GetDefaultItemObject 함수에서 BP_ItemObject에 필요한 정보들을 기입해주면 된다.
아직 마테리얼을 만들지 않았으니 만들어보도록 하자.

다음과 같이 Material Domain과 Blend Mode를 설정해서, 기본 Material과 Rotation 마테리얼을 만들도록 한다.
여기까지 무사히 마쳤다면, 아이템을 주웠을때 해당 Actor가 파괴되고, 인벤토리에 추가되는걸 확인할 수 있다.
하지만 실제로 Inventory Widget에 이미지를 추가해주는 기능은 만든적이 없으므로..
아직 육안으로 인벤토리 내 추가된 아이템을 볼수는 없을 것이다.
다음 시간에는 Widget에 해당 기능들을 추가하여 아이템을 확인하고, 움직일 수 있도록 해보자.