문제 발생
개인과제 텍스트 RPG 제작중 인벤토리를 만들던중, 인벤토리가 비어있는지 체크하고 빈 슬롯이 있으면 해당 슬롯에 아이템을 넣도록 제작하는데 null 값을 사용할 수 없는 오류가 발생했습니다.
시도해본 것
아이템은 제가 만든 구조체로, 이 정보에 ItemId 가 존재하며 생성자를 통해서 아이템을 만들때 아이템의 아이디를 필수적으로 정해주어야 합니다.
public struct Item
{
public string Name;
public string Description;
public ItemType Type;
public float ItemAttack;
public float ItemDefence;
public int ItemId;
public Item(int id, string itemName, string itemDescription, ItemType type, int attck, int defence)
{
ItemId = id;
Name = itemName;
Description = itemDescription;
Type = type;
ItemAttack = attck;
ItemDefence = defence;
}
}
또한 현재 이 게임의 첫번째 아이템의 아이디를 1로 지정해두었기 때문에 아이디가 0인 아이템은 존재하지 않습니다.
public List<Item> items = new List<Item>();
public void ResetItemList()
{
items.Add(new Item(1, "시작의 검", "처음 만들어진 검", ItemType.Weapon, 1, 0));
}
따라서 해당 슬롯의 아이템 아이디가 0일경우 빈칸으로 처리하여 문제를 해결할 수 있습니다.
//인벤토리에 아이템 획득
public void GetItem(Item item)
{
//아이템 인벤토리의 빈칸에 아이템 등록
for(int i = 0; i < inventory.Length; i++)
{
//
if (inventory[i].ItemId == 0)
{
inventory[i] = item;
break;
}
//만약, 빈칸이 없을경우(빈칸이 있으면 break를 통해 for문을 종료함)
if(i == inventory.Length)
{
Console.WriteLine("인벤토리가 가득차 아이템 획득에 실패했습니다.");
}
}
}
해결방법
단, 위의 방법이 근본적인 해결방법은 아닙니다.
이 문제의 원인은 아이템 구조체로, 구조체가 가진 모든 멤버변수는 null을 가질수 없으며 구조체가 생성될때 입력되지 않은변수들은 모두 기본값으로 초기화 됩니다.
따라서 Item 구조체를 클래스 형태로 변경할경우, 생각했던대로 배열에 빈 칸이 있을때 해당 배열에 아이템을 넣울 수 있게됩니다.
//인벤토리에 아이템 획득
public void GetItem(Item item)
{
//아이템 인벤토리의 빈칸에 아이템 등록
for(int i = 0; i < inventory.Length; i++)
{
//
if (inventory[i] == null)
{
inventory[i] = item;
break;
}
//만약, 빈칸이 없을경우(빈칸이 있으면 break를 통해 for문을 종료함)
if(i == inventory.Length)
{
Console.WriteLine("인벤토리가 가득차 아이템 획득에 실패했습니다.");
}
}
}
알게된것
class와 struct는 생성과 사용이 비슷하지만, struct는 상속을 받지 못하며 데이터를 담기 위한 그릇이기 때문에 null 값을 가지지 못한다는것을 알 수 있었습니다.
처음엔 배열로 만들어서 배열이 초기화된 상태라 생기는 문제라고 생각해서 리스트로 내용을 변경해야하나 생각했었지만,
분명 이전에 사용했던 기억이 있는 내용이라 해당 내용을 다시 확인해보니 확실히 null 여부를 사용하여 아이템을 배열에 넣어주는것을 볼 수 있었습니다.
public class Equipment : Singleton<Equipment>
{
#region Variables
private Inventory inventory;
public Item[] mainWeaponItems;
public Item[] consumWeaponItems;
public Item[] equipItems;
public UnityAction<Item, Item> OnEquipChange;
private const int armorTypeIndex = 2;
#endregion
private void Start()
{
inventory = Inventory.Instance;
mainWeaponItems = new Item[3];
consumWeaponItems = new Item[2];
equipItems = new Item[4];
for (int i = 0; i < mainWeaponItems.Length; i++)
{
equipItems[i] = new Item();
}
for (int i = 0; i < consumWeaponItems.Length; i++)
{
equipItems[i] = new Item();
}
for (int i = 0; i < equipItems.Length; i++)
{
equipItems[i] = new Item();
}
}
//주무기류 장착
public void EquipMainWeapon(Item newWeapon, int equipIndex = -1)
{
//0번 타입이 아닌 아이템 장착 시도시 실패처리
if (GetEquipIndex(newWeapon.itemId) != 0)
{
Debug.Log("잘못된 아이템 장착 시도");
return;
}
Item oldItem = null;
//슬롯지정 없이 아이템 장착 시도시
if(equipIndex == -1)
{
//비어있는 무기 슬롯에 아이템 장착, 비어있는 슬롯이 없을경우 실패처리
for(int i = 0; i <mainWeaponItems.Length; i++)
{
if(mainWeaponItems[i] == null)
{
mainWeaponItems[i] = newWeapon;
break;
}
}
Debug.Log("주무기칸이 꽉찼습니다.");
}
//슬롯을 지정하고 아이템 장착 시도시
else
{
//기존 장착된 무기가 있을경우 그 무기 저장
oldItem = mainWeaponItems[equipIndex];
//슬롯에 새로운 무기 저장
mainWeaponItems[equipIndex] = newWeapon;
//기존 장착 무기가 있을경우 인벤토리에 추가
if(oldItem != null)
{
inventory.AddItem(oldItem, true);
}
}
//장비창 새로고침
OnEquipChange?.Invoke(oldItem, newWeapon);
}
이후 혹시나 해서 Item 의 내용을 확인해본 결과, class로 정의하여 사용중이였으며 이 부분에서 문제가 발생했음을 인지하고 확인해본 결과 struct는 null 값을 가질수 없다는것을 알게 되었습니다.
해당내용으로 인해서 이미 만들어둔 내용을 바꿔줄 필요가 생기게 되었습니다...
'내일배움캠프 > TIL' 카테고리의 다른 글
내일배움캠프 8일차 TIL - 텍스트 파일을 읽을때 주의할 점 (0) | 2024.09.24 |
---|---|
내일배움캠프 7일차 TIL - 개인 프로젝트 진행 상황 돌아보기 (0) | 2024.09.23 |
내일배움캠프 5일차 TIL - 텍스트 RPG, 캐릭터 생성까지 (0) | 2024.09.19 |
내일배움캠프 5일차 TIL - DOTween 추가 정리 (0) | 2024.09.13 |
내일배움캠프 4일차 TIL - 카드게임 마무리 (0) | 2024.09.12 |