Version: Unity 6.0 (6000.0)
言語 : 日本語
スクリプトのシリアル化
カスタム製のシリアル化

シリアル化のルール

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] 属性を使用します。

追加リソース

スクリプトのシリアル化
カスタム製のシリアル化