Unity Serialization (직렬화)

🔥 Serialization (직렬화) 개요

Serialization이란 객체 데이터바이트 스트림으로 변환하여 저장하거나 전송할 수 있도록 하는 과정

주 목적은 필요할 때 다시 개체로 만들 수 있도록 개체의 상태를 저장하는 것

반대로 Deserialization은 저장된 바이트 데이터를 다시 객체로 변환하는 과정입니다.

https://learn.microsoft.com/ko-kr/dotnet/visual-basic/programming-guide/concepts/serialization/

🔥 JSON, XML, YAML

일반적으로 많이 사용하는 데이터 직렬화 포맷들


1️⃣ JSON (JavaScript Object Notation)

✔️ 특징

✅ 가벼운 텍스트 기반 포맷
✅ 사람이 읽고 쓰기 쉬우며, 기계가 빠르게 처리 가능
✅ 대부분의 프로그래밍 언어에서 지원 (C#, Python, JavaScript 등)
✅ 키-값 쌍의 구조 (Dictionary, Object와 유사)

✔️ 예제

{
  "name": "John",
  "age": 30,
  "skills": ["C#", "Unity", "Python"],
  "isDeveloper": true
}

✔️ 장점

✅ 가볍고 속도가 빠름
✅ 대부분의 언어에서 지원
✅ API 및 데이터 전송에 적합 (REST API, WebSockets 등)

❌ 단점

❌ 주석 지원이 안됨
❌ XML이나 YAML보다 덜 유연함


2️⃣ XML (eXtensible Markup Language)

✔️ 특징

✅ 데이터 구조를 계층적으로 표현 (HTML과 유사)
✅ 사람이 읽을 수 있지만, JSON보다 길이가 김
✅ 다양한 도메인에서 사용 (문서 저장, 설정 파일, 웹 서비스 등)
✅ <태그>를 이용한 구조화된 데이터 표현

✔️ 예제

<Person>
    <Name>John</Name>
    <Age>30</Age>
    <Skills>
        <Skill>C#</Skill>
        <Skill>Unity</Skill>
        <Skill>Python</Skill>
    </Skills>
    <IsDeveloper>true</IsDeveloper>
</Person>

✔️ 장점

✅ 데이터 구조가 명확함
✅ 주석 사용 가능 (<!– 주석 –>)
✅ 다양한 데이터 타입을 표현하기 적합

❌ 단점

❌ JSON보다 크기가 크고, 가독성이 떨어짐
❌ 파싱 속도가 느림


3️⃣ YAML (YAML Ain’t Markup Language)

✔️ 특징

✅ JSON과 유사하지만 더 간결한 문법을 가짐
✅ 들여쓰기를 이용한 계층 구조 (Python과 유사)
✅ 설정 파일에서 많이 사용 (Docker, Kubernetes, Unity Config 등)

✔️ 예제

name: John
age: 30
skills:
  - C#
  - Unity
  - Python
isDeveloper: true

✔️ 장점

✅ 사람이 읽기 쉬운 직관적인 문법
✅ JSON보다 간결하여 가독성이 좋음
✅ 주석 (#) 사용 가능

❌ 단점

❌ 들여쓰기 실수로 인한 오류 발생 가능
❌ 파싱 속도가 JSON보다 느림

Unity의 YAML
https://unity.com/kr/blog/engine-platform/understanding-unitys-serialization-language-yaml

🔎 비교 정리

Unity에서는 JSON (JsonUtility, Newtonsoft.Json)이 가장 많이 사용되며, YAML은 Unity의 설정 파일 (.yml)에서 많이 활용됩니다.

형식문법가독성속도사용 사례
JSON{ "key": "value" }좋음빠름 ✅API, 데이터 저장
XML<tag>value</tag>중간느림 ❌문서 저장, 설정 파일
YAMLkey: value (들여쓰기)매우 좋음 ✅중간설정 파일, DevOps

🔥Unity에서의 스크립트 직렬화 (Serialization in Unity)


1️⃣ Unity에서 직렬화가 중요한 이유

Unity는 Inspector 창에서 데이터를 유지하거나 저장 시스템(예: PlayerPrefs, JSON, Binary 파일 등)에 데이터를 저장하기 위해 직렬화를 활용합니다.

씬(Scene) 저장 및 로드: Inspector에 입력한 값이 유지됨
ScriptableObject: 게임 데이터 관리
Save/Load 시스템: JSON 또는 Binary 직렬화를 활용하여 파일 저장


2️⃣ Unity에서 직렬화 가능한 타입

https://docs.unity3d.com/6000.0/Documentation/Manual/script-serialization-rules.html

Unity는 특정 데이터 타입만 직렬화할 수 있도록 제한하고 있습니다.

⭕ 직렬화 가능한 타입 (Serializable)

기본 데이터 타입: int, float, bool, string
Unity 기본 타입: 배열 & 리스트: int[], List<float> 등 (단, public 또는 [SerializeField] 필요)
사용자 정의 클래스 ([System.Serializable] 필요)
ScriptableObject

직렬화 불가능한 타입 (Non-Serializable)

딕셔너리(Dictionary)
다차원 배열 (int[,])
속성(Property) (getter/setter)
Static 변수 (static)
추상 클래스 & 인터페이스
델리게이트(Delegate), 이벤트(Event)


3️⃣ Unity 직렬화 적용 방법

✔️ [SerializeField]

private 변수도 Inspector에서 보이도록 만들고, 직렬화 가능하게 합니다.

using UnityEngine;

public class Player : MonoBehaviour
{
    [SerializeField] private int health = 100;  // 직렬화됨 (Inspector에서 수정 가능)
    private int score = 0;  // 직렬화되지 않음 (Inspector에서 보이지 않음)
}

✅ [SerializeField]를 사용하면 private 변수도 직렬화됨
❌ 하지만 static, const, readonly 변수는 직렬화되지 않음

✔️ [System.Serializable]

사용자 정의 클래스를 직렬화하려면 [System.Serializable]을 붙여야 합니다.

using UnityEngine;

[System.Serializable]  
public class Weapon
{
    public string name;
    public int damage;
}

public class Player : MonoBehaviour
{
    public Weapon myWeapon;  // Weapon 클래스가 직렬화되므로 Inspector에서 수정 가능
}

✅ 클래스를 System.Serializable로 만들면 Unity Inspector에서 확인 가능
❌ 하지만 Dictionary, Properties, Static 변수 등은 여전히 직렬화되지 않음

✔️ ScriptableObject

게임 데이터를 저장 및 관리하는 특수한 직렬화 객체

using UnityEngine;

[CreateAssetMenu(fileName = "New Weapon", menuName = "Weapon")]
public class WeaponData : ScriptableObject
{
    public string weaponName;
    public int damage;
}

✅ 씬(Scene)과 독립적으로 데이터 관리 가능
✅ 메모리 효율적 관리 가능 (오브젝트 풀링, 설정 저장 등)
❌ 런타임에서 수정된 값은 저장되지 않음 (Play 모드가 끝나면 초기화됨)


4️⃣ Unity 직렬화와 JSON 활용

Unity에서 JSON 직렬화를 활용하면 데이터 저장 & 로드가 가능해집니다.

✔️ JsonUtility (빠르지만 제한적)

using UnityEngine;

[System.Serializable]
public class PlayerData
{
    public string name;
    public int level;
}

public class SaveLoadSystem : MonoBehaviour
{
    void Start()
    {
        PlayerData player = new PlayerData { name = "John", level = 10 };
        string json = JsonUtility.ToJson(player);
        Debug.Log(json);  // {"name":"John","level":10}

        PlayerData loadedPlayer = JsonUtility.FromJson<PlayerData>(json);
        Debug.Log(loadedPlayer.name);  // John
    }
}

✅ 빠름 & Unity 기본 지원
❌ Dictionary, List<T> 같은 복잡한 자료형 지원 X

✔️ Newtonsoft.Json (더 강력한 JSON 직렬화)

Newtonsoft.Json 라이브러리를 사용하면 Dictionary, List, Interface 등도 직렬화 가능

using UnityEngine;
using Newtonsoft.Json;
using System.Collections.Generic;

public class PlayerData
{
    public string name;
    public int level;
    public Dictionary<string, int> inventory = new Dictionary<string, int>();
}

public class SaveLoadSystem : MonoBehaviour
{
    void Start()
    {
        PlayerData player = new PlayerData { name = "John", level = 10 };
        player.inventory.Add("Sword", 1);
        player.inventory.Add("Potion", 5);

        string json = JsonConvert.SerializeObject(player, Formatting.Indented);
        Debug.Log(json);

        PlayerData loadedPlayer = JsonConvert.DeserializeObject<PlayerData>(json);
        Debug.Log(loadedPlayer.inventory["Sword"]);  // 1
    }
}

✅ Dictionary, List<T> 등 복잡한 자료형 지원
❌ JsonUtility보다 속도가 느림
❌ 추가 라이브러리 설치 필요 (Newtonsoft.Json.dll)

공부 참고 영상

댓글 달기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다

위로 스크롤