내일배움캠프 79일차 TIL : 브로셔 트러블 슈팅

woollim·2025년 1월 15일

내일배움캠프TIL

목록 보기
72/74
post-thumbnail

■ 오늘계획

○ 할 일 목록

  • 브로셔 작성
  • 버그고치기
  • 최적화


■ 브로셔 - 트러블슈팅(딕셔너리 직렬화)

💡 문제상황 & 원인분석

  • 플레이어의 인벤토리 정보를 저장하기 위해, InventoryModel을 직렬화 해야했습니다.
  • 하지만 InventoryModel의 프로퍼티들은 딕셔너리이지만, Unity의 JsonUtility는 Dictionary 타입을 기본적으로 지원하지 않습니다.
public class InventoryModel
{
    // weapon정보들 키(int)는 슬롯의 index와 같다.
    public Dictionary<int, WeaponInfo> weaponDatas { get; private set; } = new ();

    // 장비가 아닌 아이템 인벤토리. 키(int)는 슬롯의 index와 같습니다.
    public Dictionary<int, GenericItemInfo> itemDatas { get; private set; } = new ();
    // 아이템 인벤토리의 아이템 개수입니다. 키(int)는 아이템 슬롯의 index와 같습니다.
    public Dictionary<int, int> itemCounts { get; private set; } = new ();
}

📌 해결방법

  1. SerializableInventoryModel 클래스 생성
    • InventoryModel을 JSON으로 직렬화할 수 있는 형태로 변환하기 위해 만든 별도의 클래스
    • List 형태로 데이터를 저장하므로 JsonUtility를 사용할 수 있습니다.
    • 내부적으로 무기와 아이템 데이터를 각각 직렬화 가능한 WeaponData, ItemData 클래스에 담아 관리합니다.
using System.Collections.Generic;
[System.Serializable]
public class SerializableInventoryModel
{
    public List<WeaponData> weaponDatas = new List<WeaponData>();
    public List<ItemData> itemDatas = new List<ItemData>();
    public int curSlotCounts;

    [System.Serializable]
    public class WeaponData
    {
        public int slotIndex;
        public WeaponInfo weaponInfo;
    }

    [System.Serializable]
    public class ItemData
    {
        public int slotIndex;
        public GenericItemInfo itemInfo;
        public int itemCount;
    }
}

  1. 직렬화 과정

    2.1) InventoryModel → SerializableInventoryModel 변환

    • ConvertToSerializable() 함수에서 InventoryModel 데이터를 SerializableInventoryModel로 변환.
      1. InventoryModel.weaponDatas의 데이터를 순회하며 slotIndexweaponInfo를 추출.
      2. 이를 SerializableInventoryModel.WeaponData로 변환 후 weaponDatas 리스트에 추가.
      3. InventoryModel.itemDatasitemCounts의 데이터를 순회하며 slotIndex, itemInfo, itemCount를 추출.
      4. 이를 SerializableInventoryModel.ItemData로 변환 후 itemDatas 리스트에 추가.

    2.2) SerializableInventoryModel 저장

    • SaveInventoryModel()함수에서 SerializableInventoryModel을 JSON으로 저장.
      1. ConvertToSerializable()를 호출해 InventoryModel 데이터를 SerializableInventoryModel로 변환.
      2. Unity의 JsonUtility.ToJson()을 사용해 JSON 문자열로 변환.
      3. 해당 JSON 문자열을 파일(InvenDataFilePath)로 저장.
    private InventoryModel ConvertToInventoryModel(SerializableInventoryModel serializableModel)
    {
        var inventoryModel = new InventoryModel();
        inventoryModel.InitDic(serializableModel.curSlotCounts);

        foreach (var weaponData in serializableModel.weaponDatas)
        {
            if (weaponData.weaponInfo.ID == 0)
                continue;
            inventoryModel.weaponDatas[weaponData.slotIndex] = weaponData.weaponInfo;
        }

        foreach (var itemData in serializableModel.itemDatas)
        {
            if (itemData.itemCount == 0)
                continue;
            inventoryModel.itemDatas[itemData.slotIndex] = ItemFactory.CreateItem(itemData.itemInfo.ID) as GenericItemInfo;
            inventoryModel.itemCounts[itemData.slotIndex] = itemData.itemCount;
        }

        return inventoryModel;
    }

  1. 역직렬화 과정

    3.1) SerializableInventoryModel → InventoryModel 변환

    • ConvertToInventoryModel()함수에서 JSON 데이터를 InventoryModel로 변환.
      1. JSON 파일을 읽고, 이를 JsonUtility.FromJson<SerializableInventoryModel>()로 역직렬화.
      2. SerializableInventoryModel 내부의 weaponDatas 리스트를 순회하며 slotIndexweaponInfo를 추출.
      3. 이를 InventoryModel.weaponDatasDictionary에 추가.
      4. itemDatas 리스트를 순회하며 slotIndex, itemInfo, itemCount를 추출.
      5. 이를 InventoryModel.itemDatasitemCounts에 각각 추가.

    3.2) InventoryModel 로드

    LoadInventoryModel()

    함수에서 JSON 파일로부터 데이터를 읽어 InventoryModel로 변환.

    1. 저장된 파일(InvenDataFilePath)이 존재하는지 확인.
    2. 파일이 존재하지 않으면 로그를 출력하고 null 반환.
    3. 파일에서 JSON 문자열을 읽어 SerializableInventoryModel로 역직렬화.
    4. 이를 ConvertToInventoryModel()로 변환하여 InventoryModel로 변환 후 반환.
    • LoadInventoryModel()함수에서 JSON 파일로부터 데이터를 읽어 InventoryModel로 변환.
      1. 저장된 파일(InvenDataFilePath)이 존재하는지 확인.
      2. 파일이 존재하지 않으면 로그를 출력하고 null 반환.
      3. 파일에서 JSON 문자열을 읽어 SerializableInventoryModel로 역직렬화.
      4. 이를 ConvertToInventoryModel()로 변환하여 InventoryModel로 변환 후 반환.
    public InventoryModel LoadInventoryModel()
    {
        if (!System.IO.File.Exists(InvenDataFilePath))
        {
            Logger.Log("저장된 인벤토리가 없습니다.");
            return null;
        }

        string json = System.IO.File.ReadAllText(InvenDataFilePath);
        var serializableModel = JsonUtility.FromJson<SerializableInventoryModel>(json);
        Logger.Log("InventoryModel 불러오기 완료");
        return ConvertToInventoryModel(serializableModel);
    } 

  1. 전체 저장/로드 흐름
    • 저장:
      • InventoryModel → SerializableInventoryModel로 변환 → JSON 파일에 저장.
    • 로드:
      • JSON 파일 → SerializableInventoryModel로 역직렬화 → InventoryModel로 변환.

0개의 댓글