유니티 RPG - 18. 인벤토리-6(아이템 옮기기)
Intro
이번 포스팅에서는 인벤토리에서 마우스 드래그&드롭으로 아이템을 옮기거나 다른 슬롯의 아이템과 자리를 바꾸는 기능을 추가했습니다.
ItemSlotUI 클래스
슬롯에서 처리해야할것은 아이템 아이콘의 위치변경 처리입니다.
private string iconName = ""; // 현재 아이템 아이콘 이름
// 슬롯에 아이템 아이콘 등록
public void SetItemIcon(string itemSprite)
{
if(itemSprite != null)
{
// 아이콘 데이터 가져오기
ResourceManager.Instance.LoadIcon(itemSprite, sprite =>
{
// 성공
if (sprite != null)
{
// 아이콘 이름 저장
iconName = itemSprite;
// 아이콘 설정
iconImage.sprite = sprite;
ShowIcon();
}
else
{
Debug.Log($"Failed to load icon for item : {itemSprite}");
}
});
}
else
{
RemoveItemIcon();
}
}
// 다른 슬롯으로 아이템 이동
public void SwapOrMoveIcon(ItemSlotUI otherSlot)
{
// 1. 다른 슬롯이 지정되지 않았을 때
if (otherSlot == null) return;
// 2. 자기 자신일 때
if (otherSlot == this) return;
// 3. 비활성화 상태일 때
if (!this.IsAccessible || !otherSlot.IsAccessible) return;
// 1. 다른 슬롯에 아이템이 있을 때 -> 내 아이콘은 다른 슬롯의 아이콘으로 변경
if (otherSlot.HasItem) SetItemIcon(otherSlot.iconName);
// 2. 다른 슬롯에 아이템이 없을 때 -> 내 아이콘만 지우기
else RemoveItemIcon();
otherSlot.SetItemIcon(iconName);
}
- 슬롯의 현재 아이콘 이름을 저장할 itemName 를 추가했습니다.
- 따라서 아이콘이 등록될 때 아이콘 이름도 함께 저장되도록 했습니다.
- SwapOrMoveIcon 함수는 이동할 다른 슬롯의 정보를 매개변수로 받습니다.
- 다른 슬롯이 지정되지 않았거나, 자신과 자신, 비활성화 슬롯간의 교환은 무시합니다.
- 빈 슬롯으로 이동할 때는 현재 내 슬롯을 비우고 빈 슬롯에 내 아이콘을 등록합니다.
- 다른 슬롯에 아이템이 있을 때 내 슬롯은 다른 슬롯의 아이콘으로 변경합니다.
InventoryUI 클래스
InventoryUI 클래스에서는 마우스 이벤트의 처리를 구현합니다.
// 마우스 드래그 종료 처리(아이템 수량 나누기, 교환, 이동, 버리기 등)
private void EndDrag()
{
ItemSlotUI endDragSlot = RaycastAndgetFirstComponent<ItemSlotUI>();
// 아이템 이동 및 교환
if(endDragSlot != null && endDragSlot.IsAccessible)
{
TrySwapItems(beginDragSlot, endDragSlot);
}
}
// 두 슬롯 아이템 교환
public void TrySwapItems(ItemSlotUI begin, ItemSlotUI end)
{
// 자기자신 처리
if (begin == end) return;
begin.SwapOrMoveIcon(end);
inventory.Swap(begin.Index, end.Index);
}
- 마우스 이벤트 처리는 EndDrag 함수에서 처리합니다.
- 드래그하는 슬롯 정보를 가져와 TrySwapItems 함수를 호출합니다.
- TrySwapItems 함수는 ItemSlotUI의 SwapOrMoveIcon 함수를 호출하여 아이콘 위치를 변경합니다.
- 그 다음 Inventory 클래스의 Swap 함수를 호출합니다.
Inventory 클래스
Inventory 클래스에서는 실질적인 아이템 데이터의 교환이 이루어집니다.
// 인벤토리에 아이템 추가해보기(임시)
private void InitTest()
{
int testItem01 = 1001;
for(int i = 0; i<2;i++)
{
int id = testItem01 + i;
WeaponItemData weaponData = DataManager.Instance.GetDataById(id);
// 업 캐스팅(WeaponItemData => ItemData)
ItemDataArray[i] = weaponData;
// 다운 캐스팅
if (ItemDataArray[i] is WeaponItemData)
AddItem(ItemDataArray[i]);
}
}
// 인덱스 슬롯 갱신(여러 개의 슬롯) Overloading
private void UpdateSlot(params int[] indices) // index의 복수형
{
foreach(var i in indices)
{
UpdateSlot(i);
}
}
// 두 슬롯 아이템 스왑
public void Swap(int beginIndex, int endIndex)
{
// 접근불가 슬롯 처리
if (!IsValidIndex(beginIndex) || !IsValidIndex(endIndex)) return;
Item itemA = items[beginIndex];
Item itemB = items[endIndex];
// 아이템 위치 변경
items[beginIndex] = itemB;
items[endIndex] = itemA;
// 슬롯 갱신
UpdateSlot(beginIndex, endIndex);
}
- 먼저 테스트를 위해 두개의 아이템을 인벤토리에 추가했습니다.(지난번엔 한 개)
- 아이템 데이터의 교환은 Swap 함수에서 처리됩니다.
- 두 아이템 위치를 변경한 뒤 슬롯을 갱신했습니다.
- 여러개 슬롯의 갱신을 위해 UpdateSlot 함수를 Overloading 했습니다.
- index의 복수형은 indexes도 맞지만 개발쪽에선 indices 라고 사용한다고 합니다…(왜?)
댓글남기기