유니티 RPG - 31. 포션 먹기기능
Intro
이번 포스팅에서는 캐릭터 정보창을 구현하기전에, 먼저 포션아이템을 손봤습니다.
현재는 포션을 사용했을 때 별다른 동작없이 포션의 갯수만 차감되도록 되어있습니다.
이제 포션을 사용하면 체력과 마나를 회복할수있도록 기능을 추가해보았습니다.
포션을 사용하는것의 순서는 아래와같습니다.
-
인벤토리에서 사용자가 포션아이템슬롯을 우클릭
-
Inventory 클래스에 포션 사용 요청
-
Inventory 클래스의 Use() 함수에서 사용가능한 아이템인지여부 판별후 PortionItem 클래스의 Use 함수 호출
-
PortionItem 클래스에서 PlayerData에 접근하고, 포션데이터를 매개변수로 PlayerData의 UsePortion() 호출
-
PlayerData 클래스에서 UsePortion() 실행
PortionData.json
PortionData.json 파일에 포션타입을 추가했습니다.
{
"Portion": [
{
"id": 2001,
"itemName": "엘릭서",
"itemToolTip": "Hp를 일정량 회복시켜준다.",
"itemIcon": "Item_PortionItem_Elixir.png",
"maxAmount": 99,
"PortionType": "Health",
"value": 30.0
},
{
"id": 2002,
"itemName": "마나 엘릭서",
"itemToolTip": "Mp를 일정량 회복시켜준다.",
"itemIcon": "Item_PortionItem_ManaElixir.png",
"maxAmount": 99,
"PortionType": "Mana",
"value": 30.0
}
]
}
타입은 String으로, “Health” “Mana” 두가지 종류의 포션이 있습니다.
PortionItemDTO.cs
PortionItemDTO 클래스에 포션타입 필드를 추가했습니다.
[System.Serializable]
public class PortionItemDTO
{
public int id; // 아이템 id
public string itemName; // 아이템 이름
public string itemToolTip; // 아이템 툴팁
public string itemIcon; // 아이템 아이콘 이름
public int maxAmount; // 최대 소지량
public string portionType; // 포션 종류
public float value; // 회복량
}
이제 DataManager 에서 포션데이터를 가져올 때 포션타입도 가져오게되었습니다.
PortionItemData.cs
PortionItemData 클래스에 포션타입 필드를 추가했습니다.
public class PortionItemData : CountableItemData
{
[SerializeField] private float value; // 회복량
[SerializeField] private string portionType; // 포션 종류
public float Value => value;
public string PortionType => portionType;
public PortionItemData(PortionItemDTO dto)
{
this.id = dto.id;
this.itemName = dto.itemName;
this.itemToolTip = dto.itemToolTip;
this.itemIcon = dto.itemIcon;
this.maxAmount = dto.maxAmount;
this.value = dto.value;
this.portionType = dto.portionType;
}
public override Item CreateItem()
{
return new PortionItem(this);
}
}
DTO 클래스의 portionType으로 초기화하고, 프로퍼티를 추가하여 포션타입을 읽을수 있도록 했습니다.
PortionItem.cs
PortionItem 클래스에서 PortionItemData를 가지고 초기화하고,
IUsableItem 인터페이스를 구현하는 부분에서, PlayerData 클래스의 UsePortion 함수를 호출하도록 했습니다.
public class PortionItem : CountableItem, IUsableItem
{
public PortionItemData PortionData { get; private set; }
public PortionItem(PortionItemData data, int amount = 1) : base(data, amount)
{
PortionData = data;
}
// 아이템 사용
public bool Use()
{
Amount--;
DataManager.Instance.GetPlayerData().UsePortion(PortionData.Value, PortionData.PortionType);
return true;
}
}
PlayerData.cs
PlayerData 클래스에서 포션 사용에따른 플레이어의 체력과 마나를 회복하도록하는 함수를 만들었습니다.
// PlayerData.cs
// 포션 회복
public void UsePortion(float value, string type)
{
switch(type)
{
case "Health":
curHp += value;
break;
case "Mana":
curMp += value;
break;
}
}
Inventory.cs
Inventory 클래스의 UpdateSlot, Use 함수를 수정했습니다.
이후 포션아이템뿐만아니라 장비아이템 착용도 Use 함수에서 처리되도록 조건을 나누었습니다.
// 해당 인덱스 슬롯 갱신
private void UpdateSlot(int index)
{
// 유효한 슬롯만
if (!IsValidIndex(index)) return;
// 해당 아이템
Item item = items[index];
// 슬롯에 아이템 존재
if(item != null)
{
// 1. 수량이 있는 아이템인 경우
if(item is CountableItem ci)
{
// 수량이 없을 때 아이템 제거
if(ci.IsEmpty)
{
items[index] = null;
RemoveIcon();
return;
}
// 아이콘 및 수량 표시
else
{
inventoryUI.SetItemIconAndAmountText(index, item.Data.ItemIcon, ci.Amount);
}
}
// 2. 장비 아이템(임시)
else if(item is EquipmentItem ei)
{
// 아이콘 표시
inventoryUI.SetItemIconAndAmountText(index, item.Data.ItemIcon);
}
// 3. 그 외
else
{
// 아이콘 표시
inventoryUI.SetItemIconAndAmountText(index, item.Data.ItemIcon);
}
}
// 슬롯에 아이템이 없을 때
else
{
RemoveIcon();
}
// 아이콘 제거 함수
void RemoveIcon()
{
inventoryUI.RemoveItem(index);
inventoryUI.HideItemAmountText(index);
}
}
// 해당 슬롯 인덱스의 아이템 사용
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)
{
// 착용구현..
}
}
댓글남기기