Version: 2022.1
언어: 한국어
실행 시 에디터 스크립트 코드 실행
스크립트 컴파일

스크립트 직렬화

직렬화는 데이터 구조 또는 게임 오브젝트 상태를 Unity가 보관하고 나중에 다시 복구할 수 있는 포맷으로 변환하는 자동 프로세스입니다.

Unity 프로젝트에서 데이터를 정리하는 방식은 Unity가 해당 데이터를 직렬화하는 방식에 영향을 미치므로 프로젝트 성능에 상당한 영향을 미칠 수 있습니다. 이 페이지에서는 Unity의 직렬화와 직렬화를 위해 프로젝트를 최적화하는 방법에 대한 개요를 살펴봅니다.

이 문서는 다음의 항목을 다룹니다.

직렬화 규칙

Unity의 시리얼라이저는 런타임 시 효율적으로 작동하도록 특별히 고안되었습니다. 이로 인해 Unity의 직렬화는 다른 프로그래밍 환경에서의 직렬화와 다르게 동작합니다. Unity의 시리얼라이저는 해당 프로퍼티가 아닌 C# 클래스의 필드에서 직접 작동하므로 필드를 직렬화하려면 반드시 따라야하는 규칙이 있습니다. 다음 섹션에서는 Unity의 필드 직렬화를 사용하는 방법에 대한 개요를 서술합니다.

필드 직렬화를 사용하려면 필드에 대해 다음 사항을 준수해야 합니다.

  • 공용이거나 SerializeField 속성이 있어야 함
  • 정적이 아님
  • 상수가 아님
  • 읽기 전용이 아님
  • 다음과 같이 직렬화 가능한 필드 타입이 있어야 함
    • 기본 데이터 형식(int, float, double, bool, string 등)
    • 열거형 타입(32 바이트 이하)
    • 고정 크기 버퍼
    • Unity 빌트인 타입(예: Vector2, Vector3, Rect, Matrix4x4, Color, AnimationCurve)
    • Serializable 속성이 있는 커스텀 구조체
    • UnityEngine.Object에서 파생된 오브젝트에 대한 레퍼런스
    • Serializable 속성이 있는 커스텀 클래스(커스텀 클래스 직렬화 참조)
    • 위에서 언급한 필드 타입의 배열
    • 위에서 언급한 필드 타입의 List<T>

참고: Unity는 멀티 레벨 타입(다차원 배열, 가변 배열, 딕셔너리, 중첩된 컨테이너 타입)의 직렬화를 지원합니다. 이러한 타입을 직렬화하고자 하는 경우 다음의 두 가지 옵션을 선택할 수 있습니다.

커스텀 클래스 직렬화

Unity가 커스텀 클래스를 직렬화하려면 클래스가 다음 사항을 준수하는지 확인해야 합니다.

UnityEngine.Object 파생 클래스의 인스턴스를 필드에 할당하고 Unity가 해당 필드를 저장하면 Unity는 필드를 해당 인스턴스에 대한 레퍼런스로 직렬화합니다. Unity는 인스턴스를 개별적으로 직렬화하므로 여러 필드가 인스턴스에 할당될 때 중복되지 않습니다. 하지만 UnityEngine.Object에서 파생되지 않은 커스텀 클래스의 경우 Unity는 커스텀 클래스를 참조하는 MonoBehaviour 또는 ScriptableObject의 직렬화된 데이터에 인스턴스 상태를 직접 포함합니다. 이 작업은 인라인[SerializeReference]로 하는 두 가지 방식이 있습니다.

  • 인라인 직렬화: 기본적으로 Unity는 클래스를 참조하는 필드에 [SerializeReference]를 지정하지 않으면 값을 사용하여 커스텀 클래스 인라인을 직렬화합니다. 즉 일부 서로 다른 필드에 커스텀 클래스 인스턴스에 대한 레퍼런스를 보관하는 경우 필드가 직렬화되면 별개의 오브젝트가 됩니다. 그러면 Unity가 필드를 역직렬화할 때 동일한 데이터를 가진 서로 다른 오브젝트가 포함됩니다.
  • [SerializeReference] 직렬화: [SerializeReference]를 지정하면 Unity는 관리되는 레퍼런스로 오브젝트를 구축합니다. 호스트 오브젝트는 직렬화된 해당 데이터에 직접 오브젝트를 보관하지만 전용 레지스트리 섹션에는 보관하지 않습니다.

[SerializeReference]는 일부 오버헤드를 추가하지만 다음 경우를 지원합니다.

  • 필드는 null일 수 있습니다. 인라인 직렬화는 null을 나타낼 수 없지만 null을 할당되지 않은 필드가 있는 인라인 오브젝트로 교체합니다.
  • 동일한 오브젝트에 대한 여러 레퍼런스입니다. [SerializeReference]를 사용하지 않고 몇몇 다른 필드에 있는 커스텀 클래스 인스턴스에 대해 레퍼런스를 보관하면 직렬화 시 별개의 오브젝트가 됩니다.
  • 그래프와 순환 데이터(예: 자신에 대한 레퍼런스가 있는 오브젝트)입니다. 인라인 클래스 직렬화는 null 또는 공유된 레퍼런스를 지원하지 않으므로 데이터의 주기가 인스펙터의 이상한 동작이나 콘솔 오류 또는 무한 루프와 같은 예기치 못한 결과를 초래할 수 있습니다.
  • 다형성입니다. 부모 클래스에서 파생된 클래스를 생성하여 부모 클래스를 타입으로 사용하는 필드에 할당하면 [SerializeReference] 없이 Unity는 부모 클래스에 속한 필드만 직렬화합니다. Unity가 클래스 인스턴스를 역직렬화하면 파생된 클래스가 아닌 부모 클래스를 인스턴스화합니다.
  • 오브젝트의 배열 포지션을 하드 코딩하거나 전체 배열을 검색하지 않고 데이터 구조에 특정 오브젝트를 가리키는 안정적인 식별자가 필요한 경우입니다. SerializationUtility.SetManagedReferenceIdForObject를 참조하십시오.

참고: 인라인 직렬화는 더욱 효과적이며 [SerializeReference]가 지원하는 기능 중 하나가 특별히 필요한 경우가 아니라면 인라인 직렬화를 사용해야 합니다. [SerializeReference]를 사용하는 방법에 대한 자세한 내용은 SerializeReference 문서를 참조하십시오.

프로퍼티 직렬화

Unity는 다음의 경우 외에는 일반적으로 프로퍼티를 직렬화하지 않습니다.

  • 프로퍼티에 명시적 지원 필드가 있는 경우 Unity는 일반 직렬화 규칙에 따라 이를 직렬화합니다. 예는 다음과 같습니다.
public int MyInt
{
get => m_backing;
private set => m_backing = value;
}
[SerializeField] private int m_backing;
  • Unity는 핫 리로드 동안에만 자동으로 생성된 필드를 사용하여 프로퍼티를 직렬화합니다.

    public int MyInt { get; set; }

    Unity가 자동 생성된 필드로 프로퍼티를 직렬화하지 않길 원하는 경우 [field: NonSerialized] 속성을 사용합니다.

커스텀 직렬화

간혹 Unity의 시리얼라이저가 지원하지 않는 항목(예: C# 딕셔너리)을 직렬화하려는 경우가 있습니다. 가장 좋은 방법은 클래스에서 ISerializationCallbackReceiver를 구현하는 것입니다. 이를 통해 직렬화와 역직렬화 시 키 포인트에서 호출되는 콜백을 다음과 같이 구현할 수 있습니다.

  1. 오브젝트가 직렬화될 때 Unity는 OnBeforeSerialize() 콜백을 호출합니다. 이 콜백에서 Unity가 이해하는 항목으로 데이터를 변환할 수 있습니다. 예를 들어 C# 딕셔너리를 직렬화하려면 딕셔너리에서 키 배열과 값 배열로 데이터를 복사합니다.
  2. OnBeforeSerialize() 콜백이 종료되면 Unity는 배열을 직렬화합니다.
  3. 나중에 오브젝트가 역직렬화될 때 Unity는 OnAfterDeserialize() 콜백을 호출합니다. 이 콜백 안에는 메모리의 오브젝트에 편리한 폼으로 데이터를 다시 변환합니다. 예를 들어 키 배열과 값 배열을 사용하여 C# 딕셔너리를 다시 채웁니다.

Unity가 직렬화 사용하는 방법

저장 및 로드

Unity는 직렬화를 사용하여 , 에셋, 에셋 번들을 기기 메모리에 저장하거나 로드합니다. 여기에는 [MonoBehaviour](../ScriptReference/ MonoBehaviour.html) 컴포넌트와 ScriptableObjects와 같은 자체 스크립팅 API 오브젝트에 저장된 데이터가 포함됩니다.

Unity 에디터의 여러 기능은 코어 직렬화 시스템을 기반으로 제작됩니다. 직렬화와 관련해서는