유니티 RPG - 32. 방어구아이템 추가 및 방어구장착 구현
Intro
이번 포스팅에서는 방어구아이템을 추가하고, 방어구를 장착/해제할 수 있는 기능을 구현해보았습니다.
방어구는 상의(Top), 장갑(Gloves), 신발(Shoes) 데이터만 먼저 추가하기로 했습니다.
ArmorData.json 이름으로 방어구 데이터를 만들어 주었습니다.
파츠별 데이터는 카테고리를 만들어주었습니다.
{
"Top": [
{
"id": 3001,
"itemName": "낡은 갑옷",
"itemToolTip": "낡은 갑옷이다.",
"itemIcon": "Item_ArmorItem_Top_01.png",
"defense": 5,
"type": "Top"
},
{
"id": 3002,
"itemName": "단단한 갑옷",
"itemToolTip": "단단한 갑옷이다.",
"itemIcon": "Item_ArmorItem_Top_02.png",
"defense": 10,
"type": "Top"
}
],
"Shoes": [
{
"id": 4001,
"itemName": "낡은 장화",
"itemToolTip": "낡은 신발이다.",
"itemIcon": "Item_ArmorItem_Shoes_01.png",
"defense": 3,
"type": "Shoes"
},
{
"id": 4002,
"itemName": "판금 장화",
"itemToolTip": "단단한 신발이다.",
"itemIcon": "Item_ArmorItem_Shoes_02.png",
"defense": 6,
"type": "Shoes"
}
],
"Gloves": [
{
"id": 5001,
"itemName": "허름한 장갑",
"itemToolTip": "허름한 장갑이다.",
"itemIcon": "Item_ArmorItem_Gloves_01.png",
"defense": 3,
"type": "Gloves"
},
{
"id": 5002,
"itemName": "부드러운 장갑",
"itemToolTip": "부드러운 장갑이다.",
"itemIcon": "Item_ArmorItem_Gloves_02.png",
"defense": 6,
"type": "Gloves"
}
]
}
방어구는 현재 장착시 방어력만 올라가도록 했습니다.
ArmorItemData 클래스
우선 ArmorItemDTO 클래스를 만들어 데이터를 직렬/역직렬화 할 수 있도록 했습니다.
// ArmorItemDTO.cs
/*
ArmorItemData 직렬화 전용 클래스
*/
[System.Serializable]
public class ArmorItemDTO
{
public int id; // 아이템 id
public string itemName; // 아이템 이름
public string itemToolTip; // 아이템 툴팁
public string itemIcon; // 아이템 아이콘 이름
public int defense; // 방어력
public string type; // 장비타입
}
그다음, ArmorItemData 클래스를 작성합니다.
// ArmorItemData.cs
/*
ArmorItemData : 방어구 아이템 데이터
생성자 : 데이터를 받아 초기화
CreateItem() : 초기화된 데이터로 아이템 객체 생성
*/
public class ArmorItemData : EquipmentItemData
{
[SerializeField] private int defense; // 방어력
[SerializeField] private string type; // 장비타입
public int Defense => defense;
public string Type => type;
public ArmorItemData(ArmorItemDTO dto)
{
this.id = dto.id;
this.itemName = dto.itemName;
this.itemToolTip = dto.itemToolTip;
this.itemIcon = dto.itemIcon;
this.defense = dto.defense;
this.type = dto.type;
}
public override Item CreateItem()
{
return new ArmorItem(this);
}
}
ArmorItem 클래스
ArmorItem 클래스는 ArmorItemData를 받은 실제 아이템객체가 될것이고, 장비장착 및 해제를 위한 함수가 존재합니다.
장비장착 및 해제는 IEquipableItem 인터페이스를 상속받아 구현하였습니다.
// IEquipableItem.cs
public interface IEquipableItem
{
// 장비 장착
void Equip();
// 장비 장착 해제
void Unequip();
}
/*
ArmorItem : 방어구 아이템
Equip() : 방어구 장착
- 방어구 데이터의 수치만큼 플레이어 능력치 상승
Unequip() : 방어구 해제
- 방어구 데이터의 수치만큼 플레이어 능력치 하락
*/
public class ArmorItem : EquipmentItem, IEquipableItem
{
public ArmorItemData ArmorData { get; private set; }
public ArmorItem(ArmorItemData data) : base(data)
{
ArmorData = data;
}
public void Equip()
{
DataManager.Instance.GetPlayerData().EquipItem(ArmorData.Defense, ArmorData.Type);
}
public void Unequip()
{
DataManager.Instance.GetPlayerData().UnequipItem(ArmorData.Defense, ArmorData.Type);
}
}
DataManager 클래스
DataManager 클래스에서 방어구 아이템 데이터를 불러오기위한 작업을 수행합니다.
// 방어구 데이터 불러오기
private Dictionary<int, ArmorItemData> LoadArmorData()
{
if(File.Exists(armorItemDataPath))
{
string jsonData = File.ReadAllText(armorItemDataPath);
var armorDict = JsonConvert.DeserializeObject<Dictionary<string, List<ArmorItemDTO>>>(jsonData);
if(armorDict != null)
{
foreach(var category in armorDict) // "Top", "Shoes", "Gloves"
{
Dictionary<int, ArmorItemData> dataDictionary = new Dictionary<int, ArmorItemData>();
foreach (var armorDTO in category.Value)
{
ArmorItemData armorData = new ArmorItemData(armorDTO);
dataDictionary[armorData.ID] = armorData;
}
return dataDictionary;
}
}
else
{
Debug.LogWarning("Json 데이터를 파싱할 수 없습니다.");
}
}
else
{
Debug.LogWarning("불러올 파일이 없습니다.");
}
return new Dictionary<int, ArmorItemData>();
}
ArmorData.json 파일 안에 몇가지 카테고리가 있고, 그 안에 여러 데이터가 들어있기때문에 foreach 문을 2번 사용하여
데이터를 받아와 저장하였습니다.
이전에 작성한 무기데이터 및 포션데이터를 로드하는 함수도 마찬가지로 바꿔주었습니다.
Inventory 클래스
Inventory 클래스에서는 인벤토리에서 마우스 우클릭을 통해 아이템을 사용할때 호출되는 Use() 함수에서
아이템 장착을 처리하도록 했습니다.
-
사용자가 인벤토리내의 아이템을 마우스 우클릭
-
Inventory 클래스에 아이템 사용 요청(Use() 호출)
- Use() 함수에서 아이템 종류(소비, 장비 등)에 따른 아이템 사용 진행
- 이미 장착중인 장비가 있다면, 착용중인 장비를 장착해제
- 캐릭터 정보창의 아이템 아이콘을 제거한 뒤, 인벤토리에 장착해제한 아이템 추가
- 그 다음, 장비 장착 - 인벤토리내 아이템 제거 및 캐릭정보창에 아이템 등록
- 성공시 인벤토리 업데이트
// 해당 슬롯 인덱스의 아이템 사용
public void Use(int index)
{
if (!IsValidIndex(index)) return;
if (items[index] == null) return;
// 1. 소모 아이템일 때
if(items[index] is IUsableItem usable)
{
// 사용
bool success = usable.Use();
// 성공
if(success)
{
UpdateSlot(index);
}
}
// 2. 장비 아이템일 때
else if(items[index] is IEquipableItem equipable)
{
// 2.1. 무기 아이템일때
if(equipable is WeaponItem)
{
// 장착중인 아이템이 있으면 해제
if (equipmentUI.slotUIList[0].HasItem)
{
// 장착중인 아이템
WeaponItem prevItem = (WeaponItem)equipmentUI.items[0];
// 인벤토리에 장착중이던 아이템 추가
AddItem(prevItem.Data);
// 캐릭터 정보창 슬롯의 아이콘 제거
equipmentUI.slotUIList[0].RemoveItemIcon();
// 장착 해제
prevItem.Unequip();
}
// 새롭게 장착할 아이템
WeaponItem curItem = (WeaponItem)items[index];
// 장착 및 캐릭터 정보창 슬롯 아이콘 등록
equipable.Equip();
equipmentUI.SetItemIcon(curItem,curItem.WeaponData.Type, curItem.Data.ItemIcon);
}
// 2.2 방어구 아이템일때
else if(equipable is ArmorItem)
{
}
Remove(index);
UpdateSlot(index);
}
}
댓글남기기