코드 및 공부/데이터 관리

인벤토리 슬롯 저장/로드시 간헐적으로 아이템이 사라지는 현상

ekrxjvpvj0110 2024. 12. 27. 16:52

유니티 버전 - 2022.3.17f1

 

 

 

 

 

목차


  • 문제상황
  • InstanceID
  • 해결법
  • 마치며

 

 

 

 

 

문제상황


데이터 저장 / 로드시 인벤토리의 아이템 일부가 삭제되어있거나 다른 아이템이 들어있는 상황

 

 

 

현재 저장시에 Slot[]의 형태로 저장되어지고있음

 

 

 

Slot의 구조입니다, ItemSo와 itemCount는 필수로 존재해야합니다

 

 

 

또 ItemSO에는 ItemCode가 필수로 존재해야합니다

 

 

 

 

 

 

InstanceID


Json파일을 열어보았을때 저장된 Slot[i] 번째에 instanceID가 저장되어있습니다

{
  "itemSo": { "instanceID": 123456 },
  "itemCount": 5
}

// 위와 비슷하게 나옴

 

 

 

여기서 문제가 발생합니다, instanceID는 유니티의 특정 상태(런타임 / 에디터)에 의존하기 때문에 저장 및 로드 시 항상 동일한 instanceID를 보장하지 않습니다, 그래서 데이터를 저장 / 로드 했을 때, 데이터가 사라지거나 잘못된 데이터가 불러와지는 경우가 발생합니다

 

 

 

 

 

해결법


슬롯 데이터를 저장할 때 아이템의 아이템 코드를 저장하고, 불러올때는 아이템 코드를 이용해서 itemSo를 반환하여 주도록하면, instanceID를 사용하지 않고 데이터를 로드 / 저장 할 수 있습니다

 

 

 

전체 코드

public static class ItemCodeMapper
{
    /// <summary>
    /// ItemSo를 이용하여 itemCode를 반환
    /// </summary>
    public static int GetItemCode(this ItemSO p_ItemSo)
    {
        return p_ItemSo.itemCode;
    }


    /// <summary>
    /// 아이템 코드를 이용하여 ItemSo를 반환
    /// </summary>
    public static ItemSO GetItemSo(this int p_ItemCode)
    {
        return GameManager.Instance.DataBaseM.ItemDatabase.GetByID(p_ItemCode);
    }
}

 

확장 메서드를 이용하여 호출시 직관적이고 간결하게 사용 할 수 있도록 하였습니다

(정적 클래스, 정적 메서드로 정의되어야하고, 첫 번째 매개변수 앞에 this 키워드를 추가해주어야함)

 

 

GetItemCode


SaveData() 의 일부

 

 

 

GetItemCode에서는 itemSo를 받아서 itemCode를 돌려주게 설계되어있습니다

public static int GetItemCode(this ItemSO p_ItemSo)
{
    return p_ItemSo.itemCode;
}

 

 

 

 

 

GetItemSo


LoadData()의 일부

 

 

 

GetItemSo에서는 itemCode를 받고, 모든 아이템이 존재하는 ItemDatabase에서 itemCode를 이용하여 해당하는 ItemSo를 찾고, 반환하도록 하였습니다

 
public static ItemSO GetItemSo(this int p_ItemCode)
{
    return GameManager.Instance.DataBaseM.ItemDatabase.GetByID(p_ItemCode);
}

 

 

 

저장된 Json 내용

 

 

마치며


데이터베이스는 프로젝트에 맞게 설정해주시면 됩니다, 해당 프로젝트에서는 모든 아이템에 대한 정보가 딕셔너리에 들어있도록 설계되어있습니다

 

중요한 것은 InstaceID로 저장하고 불러올때 동일한 InstaceID를 보장받지 못할 수도 있다는 점입니다

 

또 ItemDatabase에 itemCode에 대응되는 ItemSo가 없을 때를 대비하는 코드를 추가한다면 더 좋을 것 같습니다

 

이상입니다