개인과제 하는 중...인벤토리
오늘은 외출하고 오느라 실시간 수업을 못 들어서 그 부분은 적을 것이 없고 대신 개인과제 진행했던 걸 좀 적어보려 한다.
public class UIInventory : MonoBehaviour
{
[SerializeField] private UISlot slotPrefab;// UISlot 타입의 필드 추가 → UISlot 프리팹 추가
[SerializeField] private Transform contentParent; //Transform 타입의 slot 부모 추가
private List<UISlot> slots = new List<UISlot>(); //UISlot 타입의 리스트 추가
private void Start()
{
InitInventoryUI();
}
public void InitInventoryUI()//UISlot 리스트, for문, Instantiate 등등 활용
{
foreach (var s in slots)
Destroy(s.gameObject);
slots.Clear();
// player의 Inventory 리스트를 가져와
var items = GameManager.Instance.player.Inventory;
for (int i = 0; i < items.Count; i++)
{
var it = items[i];
var slot = Instantiate(slotPrefab, contentParent);
slot.SetItem(it);
slots.Add(slot);
}
}
}
InitInventoryUI()가 여러번 불리게 되면 아이템이 중복 생성이 된다. 그래서 Destroy로 제거하는 방법을 쓰게 되었다.Instantiate(slotPrefab, contentParent)로 슬롯을 동적 생성한다.slot.SetItem(it)으로 슬롯에 아이템 정보를 세팅한다.public class Character
{
public int BaseAttack { get; private set; }
public int BaseDefense { get; private set; }
public int BaseHealth { get; private set; }
public int BaseCrit { get; private set; }
// 착용한 아이템 보너스를 합산
public int Attack => BaseAttack
+ Inventory.Where(i => i.IsEquipped).Sum(i => i.AttackBonus);
public int Defense => BaseDefense
+ Inventory.Where(i => i.IsEquipped).Sum(i => i.DefenseBonus);
public int Health => BaseHealth
+ Inventory.Where(i => i.IsEquipped).Sum(i => i.HealthBonus);
public int Crit => BaseCrit
+ Inventory.Where(i => i.IsEquipped).Sum(i => i.CritBonus);
public List<Item> Inventory { get; private set; }
public Character(int baseAttack, int baseDefense, int baseHealth, int baseCrit)
{
BaseAttack = baseAttack;
BaseDefense = baseDefense;
BaseHealth = baseHealth;
BaseCrit = baseCrit;
Inventory = new List<Item>();
}
public void AddItem(Item item)
{
if (item == null) return;
Inventory.Add(item);
}
public void Equip(Item item)
{
if (!Inventory.Contains(item)) return;
item.IsEquipped = true;
}
public void UnEquip(Item item)
{
if (!Inventory.Contains(item)) return;
item.IsEquipped = false;
}
}
where과 Sum
Inventory.Where(i => i.IsEquipped)는 장착된 아이템만 모아주는 필터이고
.Sum(i => i.AttackBonus)는 필터링된 아이템들의 보너스를 전부 더한다.
Contains()는 리스트에 같은 인스턴스가 들어있는지 검사한다.
public class UISlot : MonoBehaviour
{
[SerializeField] private Image slotImage; // 아이템 아이콘
[SerializeField] private GameObject equip; // 장착 중 표시
private Item item;
private Button button;
void Awake()
{
button = GetComponent<Button>();
}
public void SetItem(Item newItem)
{
item = newItem;
button.onClick.AddListener(ToggleEquip);
RefreshUI();
}
public void RefreshUI()
{
if (item != null)
{
slotImage.sprite = item.Icon;
equip.SetActive(item.IsEquipped);
}
else
{
slotImage.sprite = null;
equip.SetActive(false);
}
}
private void ToggleEquip()
{
if (item == null) return;
if (item.IsEquipped)
GameManager.Instance.player.UnEquip(item);
else
GameManager.Instance.player.Equip(item);
RefreshUI();
UIManager.Instance.uiStatus.SetStatus(GameManager.Instance.player);
}
}
RefreshUI()는 Item이 있으면 아이콘과 장착 표시를 업데이트하고 없으면 빈 슬롯이 된다.
ToggleEquip() 은 item.IsEquipped상태에 따라 Equip, UnEquip이 호출된다. 그리고 RefreshUI()로 상태를 반영하고 캐릭터 스탯도 업데이트한다.
개인적으로 아이템같은 경우는 이런 방법말고 ScriptableObject를 사용해서 했으면 더 좋았을 것 같다. 과제에 그냥 스크립트라고 적혀있고 GameManager에 아이템 생성자 데이터를 추가하라길래 일단 이렇게 마무리하게 되겠지만 아쉬운건 사실이다.
뭔가 지금까지의 개인과제들 중에서 쉬운 편에 속하는 것 같다?? 과제에서 제시해준 방법대로 구현해봤는데 뭔가... 아이템 추가하는 방식에서 약간 의아해졌지만 뭐 이런 방법도 있구나~하면서 넘어가면 될 것 같다.
내일은 주석 좀 달고 애니메이션 넣어서 조금 꾸미고 리드미 적어서 제출 할 예정이다. 그리고 오후에는 실시간 강의 놓쳤던 것들을 모아서 좀 들어보려고 한다. 그러다 보면 시간이 다 갈 것같은 느낌??