개발일기
유니티#20 인벤토리 UI, 클릭 핸들러 본문

인벤토리 슬롯은 24칸으로 늘려줬다. 8의 배수니까.
인벤토리 생성도 퀵슬롯과 거의 똑같이 해줬다. 단, 퀵슬롯에서는 slots가 RectTransform[]이었던 것에 반해, 인벤토리에서는 slots가 InventorySlot[]이었기 때문에, InventorySlot에 rectTransform 속성을 추가해주어 처리했다.
그리고 배치가 간단하고 수월했다. 극좌표계 저리가 절대좌표계 만세
중간에 클릭 핸들러라는 놈이 보일텐데, 저 놈이 오늘의 주인공이 될 녀석이다.
// Assets/Scripts/PlayerSystemManager/InventoryManager.cs
public class InventoryManager : MonoBehaviour
{
void CreateInventory()
{
for (int i = 0; i < inventorySize.x * inventorySize.y; i++)
{
GameObject slot = Instantiate(inventoryPrefab, inventoryParent.transform);
RectTransform rt = slot.GetComponent<RectTransform>();
Vector2 pos = new Vector2(200 * (i % 8) - 700, -200 * (i / 8) + 200);
rt.anchoredPosition = pos;
slots[i].rectTransform = rt;
// 클릭 핸들러 추가
var clickHandler = slot.AddComponent<InventorySlotClickHandler>();
clickHandler.slotIndex = i;
clickHandler.inventoryManager = this;
}
}
void UpdateInventory()
{
for (int i = 0; i < inventorySize.x * inventorySize.y; i++)
{
Image slotImage = slots[i].rectTransform.Find("Icon").GetComponent<Image>();
if (slots[i].itemId != 0)
{
Item item = GetItemById(slots[i].itemId);
if (item != null)
{
slotImage.sprite = item.icon;
slotImage.enabled = true;
}
}
else
{
slotImage.sprite = null;
slotImage.enabled = false;
}
TextMeshProUGUI text = slots[i].rectTransform.Find("ItemQuantity").GetComponent<TextMeshProUGUI>();
int quantity = slots[i].quantity;
text.text = (quantity == 0 ? "" : $"{quantity}");
}
}
}
// Assets/Scripts/PlayerSystemManager/InventorySlotClickHandler.cs
using UnityEngine;
using UnityEngine.EventSystems;
public class InventorySlotClickHandler : MonoBehaviour, IPointerDownHandler, IPointerEnterHandler
{
public int slotIndex;
public InventoryManager inventoryManager;
public void OnPointerDown(PointerEventData eventData)
{
if (eventData.button == PointerEventData.InputButton.Left)
{
inventoryManager.fromSlotNum = slotIndex;
inventoryManager.toSlotNum = slotIndex;
}
}
public void OnPointerEnter(PointerEventData eventData)
{
if (Input.GetMouseButton(0)) // 드래그 중일 때만
{
inventoryManager.toSlotNum = slotIndex;
}
}
}
구현해줘야 하는 기능은 마우스 드래그&드랍이다. 이 때, 바꿔야할 fromSlot과 toSlot의 정보를 저장해주고, 이 두 슬롯의 정보를 교환해줘야 한다. 또한, 마우스 버튼이 눌렸을 때 / 눌린 상태일 때 / 떼어졌을 때를 구분해서 처리해야 한다.
Unity Editor 상에서 Hierarchy의 Canvas에 컴포넌트로 Graphic Raycaster가 있고, 자식 오브젝트로 EventSystem이 있고, 누를 UI 대상의 Image 컴포넌트 속성 중 Raycas Target이 true이면 OnPointerDown, OnPointerEnter로 각 상황을 처리할 수 있다.
주석으로 달아둔 '클릭 핸들러 추가' 부분은 위의 해당 스크립트를 소환하는 각각의 오브젝트에 할당해주는 부분인 것이다.
그렇게 fromSlotNum과 toSlotNum이 확보가 된다면, 각 슬롯의 정보만 교환해주면 끝.
// Assets/Scripts/PlayerSystemManager/InventoryManager.cs
public class InventoryManager : MonoBehaviour
{
void SwapItem(int fromNum, int toNum)
{
if (fromNum == toNum) return;
// 아이템 정보만 교환
int tempId = slots[fromNum].itemId;
int tempQty = slots[fromNum].quantity;
slots[fromNum].itemId = slots[toNum].itemId;
slots[fromNum].quantity = slots[toNum].quantity;
slots[toNum].itemId = tempId;
slots[toNum].quantity = tempQty;
// UI 업데이트
UpdateInventory();
}
}
여담) 내가 보기에 퀵슬롯이랑 인벤토리 코드 통합할 수 있을 것 같긴 한데 귀찮고 막 그르네
안 하는 게 나을 것 같기도
'Unity' 카테고리의 다른 글
| 유니티#21 와 맛있다 PlayerInput, Physics Material 2D, Effect (0) | 2025.05.20 |
|---|---|
| 유니티#20.5 총 (0) | 2025.05.03 |
| 유니티#19 인벤토리, 퀵슬롯, 아이템 시스템 제작 (0) | 2025.04.30 |
| 유니티#18 Rigidbody2D 아이템 줍기 구현 (1) | 2025.04.29 |
| 유니티#17 Animation Controller, Override Controller (0) | 2025.04.12 |
