[2025_11_18]ItemScriptableObject생성 및 Json과 연동

2025. 11. 18. 21:00TIL

문제 상황

Addressable로 JSON 데이터를 로드하려는데 계속 실패했다.

 
 
JSON 로드 완료: 0개 (Data/Item)

분명 JSON 파일도 있고, Addressable 설정도 확인했는데 아무것도 로드되지 않았다.


해결 과정

1. Addressable 설정 확인

  • 주소: "Data/Item" - 정상
  • 경로: Assets/Data/ItemData.json - 존재함
  • 라벨: "Item" - 설정됨
  • Build: Addressable Group도 빌드됨

Addressable은 문제 없음

2. JSON 파일 구조 확인

 
json
{
  "items": [
    {
      "id": 1,
      "itemName": "체력 물약",
      "description": "HP를 50 회복",
      "itemType": "Consumable",
      "value": 50,
      "duration": 0
    }
  ]
}

JSON 구조도 정상

3. 로드 코드 확인

 
csharp
private async void LoadJsonData()
{
    var handle = Addressables.LoadAssetAsync<TextAsset>("Data/Item");
    await handle.Task;
    
    if (handle.Status == AsyncOperationStatus.Succeeded)
    {
        string jsonText = handle.Result.text;
        ItemJsonDatabase db = JsonUtility.FromJson<ItemJsonDatabase>(jsonText);
        Debug.Log($"JSON 로드 완료: {db.items.Count}개");  // 0개 출력!
    }
}

코드도 문제없어 보임


 원인 발견

문제는 데이터 클래스에 있었다!

 
csharp
//이렇게 되어 있었음
public class JsonDatabase<T> 
{ 
    public List<T> items = new List<T>(); 
}

public class ItemJsonDatabase : JsonDatabase<ItemJsonData> { }

public class ItemJsonData 
{ 
    public int id; 
    public string itemName; 
    public string description; 
    // ...
}

JsonUtility는 [Serializable]이 없는 클래스를 직렬화하지 못한다!


해결 방법

각 클래스에 [Serializable] 추가:

 
csharp
[System.Serializable]
public class JsonDatabase<T> 
{ 
    public List<T> items = new List<T>(); 
}

[System.Serializable]
public class ItemJsonDatabase : JsonDatabase<ItemJsonData> { }

[System.Serializable]
public class ItemJsonData 
{ 
    public int id; 
    public string itemName; 
    public string description; 
    public string itemType; 
    public int value; 
    public float duration; 
}


결과:

JSON 로드 완료: 15개 (Data/Item)

핵심 개념: JsonUtility의 직렬화 요구사항

JsonUtility.FromJson()이 동작하려면:

  1. 클래스에 [Serializable] 필수
 
 
csharp
   [System.Serializable]  // 이거 없으면 안 됨!
   public class MyData { }
  1. 필드는 public이거나 [SerializeField]
 
 
csharp
   [System.Serializable]
   public class MyData 
   {
       public int id;                  
       [SerializeField] private string name;  
       private float value;              
   }
  1. 제네릭 클래스도 [Serializable] 필요
 
 
csharp
   [System.Serializable]
   public class JsonDatabase<T>  // 제네릭도 필수!
   {
       public List<T> items;
   }
  1. 상속받은 클래스도 마찬가지
 
 
csharp
   [System.Serializable]
   public class ItemJsonDatabase : JsonDatabase<ItemJsonData>  // 이것도!
   { }

---

## 왜 이렇게 만들었나?

### **설계 의도: 기획자 친화적 데이터 관리**
기획자(Unity 모름)
    ↓
  JSON 파일 수정
    ↓
ScriptableObject로 자동 변환
    ↓
  게임에서 사용

장점:

  • 기획자가 Unity 안 열어도 됨
  • Excel -> JSON 변환 가능
  • Git으로 버전 관리 용이
  • ScriptableObject의 장점도 활용

구조:

 
 
csharp
// 1. JSON 파싱용 클래스
[System.Serializable]
public class ItemJsonData { /* JSON 구조와 1:1 매핑 */ }

// 2. ScriptableObject (Unity에서 사용)
public class ItemData : ScriptableObject 
{
    // JSON → ScriptableObject 변환
    public void InitFromJson(ItemJsonData jsonData) 
    {
        this.id = jsonData.id;
        this.itemName = jsonData.itemName;
        // ...
    }
}

// 3. DataManager가 중개
public class DataManager
{
    public void LoadJsonData()
    {
        // JSON 로드 → ItemJsonData
        // ItemJsonData → ItemData ScriptableObject 생성
    }
}

추가로 알게 된 점

JsonUtility vs Newtonsoft.Json

기능JsonUtilityNewtonsoft.Json

속도 빠름  느림
[Serializable] 필수 선택
private 필드 [SerializeField] 필요 자동 지원
Dictionary 지원 안 함 지원
복잡한 구조 제한적 강력

언제 뭘 써야 할까?

  • 간단한 데이터 + 성능 중요 -> JsonUtility
  • 복잡한 구조 + 편의성 중요 -> Newtonsoft.Json

 교훈

  1. JsonUtility 쓸 땐 [Serializable] 체크리스트
    • 모든 클래스에 [Serializable]
    • 제네릭 클래스도 확인
    • 상속받은 클래스도 확인
  2. 디버깅 팁
 
csharp
   // JSON이 실제로 뭐가 들어왔는지 확인
   Debug.Log($"JSON 원본:\n{jsonText}");
   
   // 파싱 결과 확인
   var db = JsonUtility.FromJson<ItemJsonDatabase>(jsonText);
   Debug.Log($"items null? {db.items == null}");
   Debug.Log($"items count: {db.items?.Count ?? 0}");

 

프로젝트 초기에 데이터 파이프라인 설계

  • 기획자가 어떻게 수정할지
  • 어떤 포맷으로 관리할지
  • 변환 과정은 어떻게 할지

 관련 개념

  • Unity Serialization
  • Addressable Asset System
  • ScriptableObject
  • JSON 파싱
  • Data-Driven Development