인벤토리의 아이템을 스크립트를 통해 생성하고 관리하는 시스템으로 만들어보았다.
플레이어가 가지고 있는 아이템 리스트의 내용에 따라 UI요소가 생성되고 변경된다.
유니티에서 준비하기
프리팹 설정
기본적으로 스크립트를 통해 요소를 생성할 때, 프리팹을 활용한다. 각 아이템 타입별로 UI요소의 특징이 조금씩 다르기 때문에 이를 반영하여 각각의 프리팹을 만들었다.
프리팹은 Resources 폴더를 활용하는 방식으로 스크립트로 불러왔다. 이에 대한 이야기는 나중에,,,
플레이어가 가지고 있는 아이템리스트의 아이템들은 고유의 sprite를 갖는다. 프리팹의 이미지를 이 sprite로 교체해서 원하는 UI 컴포넌트를 얻게 된다.
생성된 UI 요소는 Scrol View(UI 요소)의 하위 요소인 Content로 들어가도록 설정했다.
(Content - 여기가 실제로 스크롤 되는 콘텐츠가 담기는 공간)
(Clone)이 붙은 것에서 알 수 있듯이, Instantiate를 통해 생성된 오브젝트들이다.
UI 요소 정렬
+ 이 오브젝트들이 담긴 Content 오브젝트에 "Grid Layout Group" 컴포넌트를 추가해서 자식요소들의 정렬을 설정해두면 Clone되어 생성되는 오브젝트들의 위치가 자동으로 정렬된다.
스크립트
세팅하기
public Dictionary<string, GameObject> ItemTypeDict = new Dictionary<string, GameObject>();
private List<Items> inventoryItems;
public List<GameObject> inventoryObjects;
public Transform InventoryPos;
private void Awake()
{
inventoryItems = GameManager.instance.inventory.InventoryItems;
inventoryObjects = new List<GameObject>();
GameObject[] loadedObjects = Resources.LoadAll<GameObject>("ItemTypes");
foreach (var obj in loadedObjects)
{
ItemTypeDict[obj.name] = obj;
}
}
- 우선 프리팹과 아이템 정보 등의 기본 데이터를 세팅한다.
- 아이템 리스트(intentoryItems)에 있는 아이템들을 타입에 맞는 프리팹과 연결시키기 위해 Dictionary를 썼다.
- 각 프리팹의 이름을 키로 갖고 프리팹 오브젝트를 벨류로 갖는 딕셔너리를 만들었다.
- 나중에 아이템의 종류에 따라 프리팹을 이름으로 찾기 위해서임
- Resources.LoadAll<GameObject>("ItemTypes");
- Resources라는 폴더를 Asset 하위 어딘가에 만들어 두면, Resources.Load 또는 Resources.LoadAll과 같은 메서드를 통해서 원하는 에셋을 스크립트로 가져올 수 있게 된다.
- 현재 스크립트에서는 Resources폴더의 하위 폴더인 "ItemTypes"에서 <GameObject>타입의 에셋을 모두 불러와서 GameObject 배열에 담고 있다.
UI 요소 생성 메서드
void CreateInventoryItems()
{
RectTransform rectTransform = InventoryPos as RectTransform;
rectTransform.sizeDelta = new Vector2(rectTransform.sizeDelta.x, 400f);
foreach (Items item in inventoryItems)
{
GameObject obj = Instantiate(ItemTypeDict[$"Item_{item.Type.ToString()}"], InventoryPos);
Image iconImg = obj.transform.GetChild(2).GetComponent<Image>();
iconImg.sprite = item.itemIcon;
obj.GetComponent<EquipController>().itemInfo = item;
inventoryObjects.Add(obj);
}
if (inventoryItems.Count <= 9)
{
for (int i = 0; i < 9 - inventoryItems.Count; i++)
{
GameObject obj = Instantiate(ItemTypeDict["ItemBg"], InventoryPos);
}
}
else
{
rectTransform.sizeDelta = new Vector2(rectTransform.sizeDelta.x, ((float)Math.Ceiling((float)inventoryItems.Count / 3) * 130) + 10);
if (inventoryItems.Count % 3 != 0)
{
for (int i = 0; i < 3 - (inventoryItems.Count % 3); i++)
{
GameObject obj = Instantiate(ItemTypeDict["ItemBg"], InventoryPos);
}
}
}
}
- InventoryPos는 아이템을 담을 부모 요소(Content)
- foreach 부분이 아이템 UI 요소를 실제로 생성하는 부분이다.
- 생성하고자 하는 아이템의 ItemType을 가져와서 Dictionary를 통해 해당 프리팹을 찾는다.
- Image iconImg = obj.transform.GetChild(2).GetComponent<Image>(); 부분에서 GetChild(2)는 프리팹의 세 번째 자식 요소를 가리키는데, 아이템 고유의 아이콘이미지를 담는 부분이다.
- 아래 부분은 UI를 보다 깔끔하게 만들기 위한 추가 조치이다.
- 인벤토리에서 기본적으로 보이는 아이템의 수가 9개이므로, 이보다 아이템 개수가 작을 때는 빈 공간을 비워두는 것이 아니라, 빈 칸 전용 프리팹을 추가했다.
- 뿐만 아니라, 9보다 클 때에도 가로로 한 행에 아이템 세 개씩 정렬되므로, 세 개 모두 차지 않은 행은 빈 칸 전용 프리팹을 추가해서 행에 빈 영역이 없도록 했다.
- Content가 하위요소들을 담고 있는 영역의 크기 또한 계산해서 맞추어주었다.
'👾 내일배움캠프 > 🎮 TIL & WIL' 카테고리의 다른 글
내일배움캠프 (휴일) TIL - 플레이어의 움직임 추가 공부 (0) | 2023.09.24 |
---|---|
내일배움캠프 33일차 TIL - 초기화와의 싸움 (0) | 2023.09.23 |
내일배움캠프 32일차 TIL - 애니메이션 UI에 적용 (0) | 2023.09.21 |
내일배움캠프 31일차 TIL - 프레임과 timeScale (0) | 2023.09.21 |
내일배움캠프 30일차 TIL - 스크립트 분리 (0) | 2023.09.21 |