유니티로 개발하면서 게임에서 플레이어에게 필요한 데이터들을 앱을 종료하고 실행시켰을 때, 그대로 불러오는 기능을 구현해야 하는 경우가 자주 생깁니다.
이럴 때는 종종 저장해야 할 값이나 객체를 JSON 포멧으로 바꾸어 .json 파일 형식으로 저장하고 불러오는 기능을 사용합니다.
또한, 클래스의 private 멤버변수를 개발 할 때의 편의를 위해 인스펙터 창에서 볼 수 있도록 [SerializeField] 키워드를 이용하기도 합니다.
이런 기능들은 직렬화(Serialization)라는 과정을 통해 가능한 일들입니다.
직렬화(Serialization)란, 데이터 구조나 오브젝트를 컴퓨터 환경에 저장하고 나중에 재구성 할 수 있는 포멧으로 변환하는 과정을 의미합니다.
그렇다고 모든 데이터들을 다 직렬화 할 수 있는 것은 아니고, 직렬화 규칙이 있습니다.
다음 규칙을 지키는 데이터들을 직렬화 할 수 있습니다.
- public이거나 SerializeField 속성이 있어야 함
- 정적이 아님
- 상수가 아님
- 읽기 전용이 아님
- 다음과 같이 직렬화 가능한 필드 타입이 있어야 함
- 기본 데이터 형식(int, float, double, bool, string 등)
- 열거형 타입(32 바이트 이하)
- 고정 크기 버퍼
- Unity 빌트인 타입(예: Vector2, Vector3, Rect, Matrix4x4, Color, AnimationCurve)
- Serializable 속성이 있는 커스텀 구조체
- UnityEngine.Object에서 파생된 오브젝트에 대한 레퍼런스
- Serializable 속성이 있는 커스텀 클래스(커스텀 클래스 직렬화 참조)
- 위에서 언급한 필드 타입의 배열
- 위에서 언급한 필드 타입의 List< T >
예시로, 아래 클래스의 요소들처럼 직렬화 규칙을 만족하는 멤버들은 인스펙터 창에 직렬화되어 나타나는 것을 볼 수 있습니다.
public class SerializeScript : MonoBehaviour
{
public enum MyEnum { AAA, BBB, CCC }
[System.Serializable]
public class MyClass
{
public int intValue;
public List<int> intListValue;
public MyEnum myEnum;
}
public int publicValue;
[SerializeField]
private int serializedPrivateValue;
static int staticValue;
public const int constValue = 10;
public readonly int readonlyValue = 10;
public MyClass myClass = new MyClass();
}
인스펙터는 오브젝트의 직렬화 조건을 갖춘 필드들을 보여주며, 인스펙터 창에서 값을 수정하면, 직렬화된 데이터를 업데이트하고 역직렬화를 수행하여 오브젝트에 적용됩니다.
Json을 유니티에서 직렬화 할 때는 JsonUtility 클래스를 사용할 수 있습니다.
JsonUtility는 유니티에서 지원하는 Json 데이터 처리 클래스입니다.
JsonUtility를 사용하여 직렬화 및 역직렬화 할 때는 다음의 조건이 필요합니다.
- 직렬화하려는 데이터가 "구조화"된 데이터여야 한다. 즉, 저장하려는 변수를 클래스나 구조체로 표현해야 합니다.
- Monobehavior 혹은 ScriptableObject를 상속받은 클래스이거나, [Serializable] 속성을 가진 클래스여야 합니다.
- 단순 변수나 배열은 직렬화하지 못하며, 클래스 혹은 구조체를 사용하여 나타내야 합니다.
이제 직렬화 및 역직렬화를 사용하는 방법을 코드를 통해 알아보겠습니다.
직렬화 방법
1. 직렬화 할 데이터의 구조를 클래스 혹은 구조체로 선언합니다.
2. 해당 클래스(구조체)에 [Serializable] 속성을 붙여 직렬화 가능하게 만듭니다.[Serializable] public class MyClass { public int level; public float timeElapsed; public string playerName; }
- 직렬화 할 클래스를 선언하고 값을 초기화합니다.
MyClass myObject = new MyClass(); myObject.level = 1; myObject.timeElapsed = 47.5f; myObject.playerName = "Dr Charles Francis";
- JsonUtility.ToJson() 메서드를 사용해 클래스를 json 포맷의 문자열로 생성합니다.
string json = JsonUtility.ToJson(myObject); // json now contains: '{"level":1,"timeElapsed":47.5,"playerName":"Dr Charles Francis"}'
역직렬화 방법 (위 코드 참고)
1. Json 포멧의 문자열 데이터와 동일한 구조의 클래스의 인스턴스를 선언합니다.
2. JsonUtility.FromJson< T >() 메서드를 통해 문자열 데이터를 해당 클래스의 구조로 매핑합니다.myObject = JsonUtility.FromJson<MyClass>(json);
! 여기서 변환할 클래스의 구조에 없는 데이터는 무시됩니다.
참고자료
https://docs.unity3d.com/kr/2021.3/Manual/script-Serialization.html