Unity에서 JSON 데이터를 다루는 방법은 여러가지가 있지만
가장 널리 쓰이는 방식은 다음 두 가지를 많이 사용합니다.
하나는 JsonUtility(Unity 내장 방식), 다른 하나는 Newtonsoft.Json(외부 라이브러리) 입니다.
이 글에서는 이 두 가지 방법을 비교해보고,
외부에서 JSON 파일을 불러와 직접 파싱하는 과정을 알아보겠습니다.
JsonUtility
JsonUtility는 메서드가 유니티에 내장되어 있으므로 별도의 설치 없이 그대로 사용합니다.
// 직렬화/역직렬화 할 요소를 별도의 구조로 만듬(구조체 또는 클래스)
[System.Serializable]
public class Item
{
public int id;
public string name;
public string description;
}
[System.Serializable]
public class ItemDataList
{
public List<Item> Item;
}
데이터를 직렬화하거나 역직렬화할 땐, 먼저 이렇게 클래스를 만듭니다.
Item 클래스는 개별 아이템 하나의 구조를 정의하고,
ItemDataList 클래스는 그걸 리스트 형태로 담는 역할을 합니다.
여기서 중요한 건 아래처럼 JSON에 "Item"이라는 키가 있을 경우,
ItemDataList 클래스 안에서도 Item이라는 이름(대소문자 포함)을 정확히 맞춰줘야
JsonUtility가 정상적으로 매핑해줍니다.
예를 들어 JSON이 이렇게 생겼다면:
{
"Item": [
{ "id": 1, "name": "단검", "description": "짧은 단검" }
]
}
클래스 내부 필드도 정확히 "Item"이라는 이름이어야 매칭됩니다.
public class MonsterLoader : MonoBehaviour
{
public static MonsterLoader Instance;
public List<Monster> monsterList;
void Start()
{
TextAsset jsonData = Resources.Load<TextAsset>("Monster");
ItemDataList wrapper = JsonUtility.FromJson<ItemDataList>(jsonData.text);
// 역직렬화된 결과에서 실제 몬스터 리스트를 추출하여 monsterList 변수에 저장
// 여기서 wrapper.Monster는 JSON의 "Monster" 배열을 파싱한 결과이기 때문에,
// 이걸 실제 게임에서 사용할 변수 monsterList에 저장하는 것
monsterList = wrapper.Monster;
}
}
[System.Serializable]
public class Monster
{
public string MonsterID;
public string Name;
public string Description;
public int Attack;
public float AttackMul;
public int MaxHP;
public float MaxHPMul;
public int AttackRange;
public float AttackRangeMul;
public float AttackSpeed;
public float MoveSpeed;
public int MinExp;
public int MaxExp;
public int[] DropItem;
}
[System.Serializable]
public class MonsterList
{
public List<Monster> Monster;
}
Resources.Load를 통해 JSON 파일을 불러온 뒤
JsonUtility.FromJson 메서드를 사용해서 JSON 데이터를 역직렬화 합니다.
이때 JSON 구조에 맞게 만들어둔 ItemDataList 클래스를 통해 전체 데이터를 감싼 후,
그 안에서 실제 아이템 리스트(List<Item>)만 꺼내 itemList 변수에 복사해 두는 방식
[실제 사용하기]
리스트를 사용해서 적용
public class MonsterLoader : MonoBehaviour
{
public static MonsterLoader Instance;
public List<Monster> monsterList;
void Start()
{
TextAsset jsonData = Resources.Load<TextAsset>("Monster");
MonsterList wrapper = JsonUtility.FromJson<MonsterList>(jsonData.text);
monsterList = wrapper.Monster;
}
}
public class KnifeAttack : MonoBehaviour
{
public string monsterId = "M0001";
[SerializeField] private float attackRange;
private void Start()
{
foreach (var m in MonsterLoader.Instance.monsterList)
{
if (m.MonsterID == monsterId)
{
attackRange = m.AttackRange + m.AttackRangeMul;
}
}
}
public void Attack()
{
Collider2D[] targets = Physics2D.OverlapCircleAll(transform.position, attackRange);
}
}
딕셔너리를 사용해서 적용
public class MonsterLoader : MonoBehaviour
{
public static MonsterLoader Instance;
public List<Monster> monsterList;
// 키(key)를 기반으로 값을 빠르게 조회하기(Tkey(MonsterID : M0001), Tvalue(Monster 객체))
public Dictionary<string, Monster> monsterDict = new Dictionary<string, Monster>();
void Start()
{
TextAsset jsonData = Resources.Load<TextAsset>("Monster");
MonsterList wrapper = JsonUtility.FromJson<MonsterList>(jsonData.text);
monsterList = wrapper.Monster;
// JSON에서 로드된 모든 몬스터를 순회하면서
// 각 몬스터의 MonsterID를 key로, Monster 객체를 value로 딕셔너리에 저장
foreach (var monster in monsterList)
{
monsterDict[monster.MonsterID] = monster;
}
}
}
public class KnifeAttack : MonoBehaviour
{
public string monsterId = "M0001";
[SerializeField] private float attackRange;
private void Start()
{
// monsterId에 해당하는 몬스터 데이터를 딕셔너리에서 가져옴
// 찾으면 monster에 값이 들어가고 true 반환, 못 찾으면 false.
if (MonsterLoader.Instance.monsterDict.TryGetValue(monsterId, out Monster monster))
{
attackRange = monster.AttackRange + monster.AttackRangeMul;
}
}
public void Attack()
{
Collider2D[] targets = Physics2D.OverlapCircleAll(transform.position, attackRange);
}
}
Newtonsoft.Json
Unity는 기본적으로 Newtonsoft.Json을 지원하지 않기 때문에
JsonUtility와 다르게 별도의 설치 과정이 존재합니다.
[Windows] → [Package Manager]에서 [Add package by name...] 클릭
com.unity.nuget.newtonsoft-json 를 입력 후 Version(선택) 입력 후 [Add]
using Newtonsoft.Json;
설치가 완료되면 using Newtonsoft.Json 네임스페이스를 사용할 수 있습니다.
using Newtonsoft.Json;
public class ItemLoaderNewtonsoft : MonoBehaviour
{
public List<Item> itemList;
void Start()
{
TextAsset jsonData = Resources.Load<TextAsset>("Item"); // Resources 폴더 안의 Item.json
ItemDataList wrapper = JsonConvert.DeserializeObject<ItemDataList>(jsonData.text);
itemList = wrapper.Items;
}
public void UseItem()
{
foreach (Item item in itemList)
{
Debug.Log(item.id);
}
}
}
public class Item
{
[JsonProperty("id")]
public int id;
[JsonProperty("name")]
public string name;
[JsonProperty("description")]
public string description;
}
public class ItemDataList
{
[JsonProperty("Item")] // JSON의 "Item" 키와 정확히 매핑
public List<Item> Items;
}
Resources.Load를 통해 JSON 파일을 불러온 뒤
JsonConvert.DeserializeObject 메서드를 사용해서 JSON 데이터를 역직렬화 합니다.
이때 JsonUtility와 다르게 JsonProperty(변수명이 다를때 치환)를 이용해서
JSON의 키 이름(예: "Item", "id", "name")과 C# 클래스의 변수명이 달라도 정확히 매핑할 수 있습니다.
역직렬화 결과로 감싸진 클래스(ItemDataList) 안의 Items 리스트를 꺼내서
itemList 변수에 저장하면 게임에서 아이템 정보를 자유롭게 쓸 수 있습니다.
'Unity' 카테고리의 다른 글
오브젝트가 화면을 나가면 사라지게 하기(OnBecameInvisible) (0) | 2025.05.13 |
---|---|
[유니티] Mathf.Abs를 통한 방향 전환 (0) | 2025.05.12 |
[Unity] 직렬화(Serialization) (0) | 2025.05.09 |
[Unity] UI(User Interface) (0) | 2025.04.26 |
[Unity] 월드좌표, 로컬좌표 (0) | 2025.04.24 |