ドキュメント

Unity Engine

Unity Engine

シリアル化のルール

Conditions that determine whether fields in your scripts are serialized.
読み終わるまでの所要時間 11 分最終更新 1ヶ月前

Unity のシリアライザーは、特にランタイムで効率的に動作するように設計されています。そのため、Unity のシリアル化は、他のプログラミング環境のシリアル化とは異なる挙動をします。Unity のシリアライザーは、プロパティではなく C# クラスのフィールドで直接機能します。そのため、Unity は特定の条件を満たす場合にのみフィールドをシリアル化します。以下のセクションでは、Unity でフィールドのシリアル化を行う方法の概要を説明します。
フィールドシリアライゼーションを使用するには、フィールドが以下の状態であることを確認します。
  • public
    または SerializeField 属性を持つこと。
    • ノート: 場合によっては、
      private
      フィールドがシリアル化されます。詳しくはホットリロードを参照してください。
  • static
    でないこと。
  • const
    でないこと。
  • readonly
    でないこと。
  • シリアラル化可能なフィールド型であること。
    • プリミティブなデータ型 (int、float、double、bool、string など) であること。
    • Enum 型 (32 バイト以下) であること。
    • 固定サイズバッファであること。
    • Unity の組み込み型 (例えば、Vector2、Vector3、Rect、Matrix4x4、Color、AnimationCurve) であること。
    • Serializable 属性をもつカスタム構造体であること。
    • UnityEngine.Object から派生したオブジェクトを参照すること。
    • Serializable 属性を持つカスタムクラスであること。(カスタムクラスのシリアル化 を参照)。
    • 上記のフィールド型の配列であること。
    • 上記のフィールド型の
      List<T>
      であること。
ノート: Unity は、マルチレベルの型 (多次元配列、ジャグ配列、辞書、ネストされたコンテナタイプ) のシリアル化をサポートしていません。これらをシリアル化するには 2 つのオプションがあります。

カスタムクラスのシリアル化

Unity がカスタムクラスをシリアライズするためには、クラスが以下の状態であることが必要です。
  • Serializable 属性を持つこと。
  • static でないこと。
UnityEngine.Object
から派生したクラスのインスタンスをフィールドに割り当て、そのフィールドを保存する場合、Unity はフィールドをシリアル化してそのインスタンスへの参照にします。Unity はそのインスタンス自体を個々にシリアル化します。そのため、インスタンスに複数のフィールドが割り当てられても重複しません。しかし、
UnityEngine.Object
から派生しないカスタムクラスの場合、Unity はインスタンスの状態を、それらを参照する MonoBehaviour や ScriptableObject のシリアル化されたデータに直接加えます。これには、インラインと
[SerializeReference]
の 2 つの方法があります。
  • インラインでシリアル化:デフォルトでは、クラスを参照するフィールドに
    [SerializeReference]
    を指定しない場合、Unity はカスタムクラスを値によってインラインでシリアル化します。つまり、カスタムクラスのインスタンスへの参照を複数の異なるフィールドに保存する場合、それらはシリアル化されると別々のオブジェクトになります。フィールドをデシリアライズすると、それらは同一のデータを持つ異なる別個のオブジェクトを含みます。
  • [SerializeReference]
    でシリアル化
    :
    [SerializeReference]
    を指定する場合、Unity はオブジェクトをマネージ参照として確立します。ホストオブジェクトは、オブジェクトをそのシリアル化されたデータに直接保存しますが、専用のレジストリセクションに格納します。
[SerializeReference]
は若干のオーバーヘッドを追加しますが、以下のケースをサポートします。
  • フィールドは null でも可。インラインのシリアル化では、null を表現できません。代わりに、null を未割り当てのフィールドを持つインラインオブジェクトに置き換えます。
  • 同じオブジェクトへの複数の参照。
    [SerializeReference]
    を使用せずに、カスタムクラスのインスタンスへの参照を複数の異なるフィールドに格納する場合、それらはシリアル化すると別々のオブジェクトになります。
  • グラフと循環データ (例えば、それ自体への参照を持つオブジェクト)。インラインクラスのシリアル化は、null や参照の共有をサポートしません。そのため、データの循環は、Inspector の動作の異常、コンソールエラー、無限ループなど、予期しない結果につながる可能性があります。
  • ポリモーフィズム。親クラスから派生したクラスを作成し、親のクラスを型として使用するフィールドに割り当てる場合、
    [SerializeReference]
    なしに、Unity は親クラスに属するフィールドのみをシリアル化します。Unity はクラスインスタンスをデシリアライズするとき、派生クラスではなく、親クラスをインスタンス化します。
  • データ構造体が、オブジェクトの配列位置をハードコードしたり配列全体を検索したりせずに、特定のオブジェクトを指し示す安定した識別子を必要とする場合。Serialization.ManagedReferenceUtility.SetManagedReferenceIdForObject を参照してください。
ノート: インラインのシリアル化はより効率的なので、
[SerializeReference]
がサポートする機能の 1 つを特に必要としない限り、インラインのシリアル化を使用することをお勧めします。
[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]
属性を使用します。

追加リソース