# シリアル化のルール

> Conditions that determine whether fields in your scripts are serialized.

Unity のシリアライザーは、特にランタイムで効率的に動作するように設計されています。そのため、Unity のシリアル化は、他のプログラミング環境のシリアル化とは異なる挙動をします。Unity のシリアライザーは、プロパティではなく C# クラスの**フィールド**で直接機能します。そのため、Unity は特定の条件を満たす場合にのみフィールドをシリアル化します。以下のセクションでは、Unity でフィールドのシリアル化を行う方法の概要を説明します。

フィールドシリアライゼーションを使用するには、フィールドが以下の状態であることを確認します。

* `public` または [SerializeField](/engine/6000.0/script-reference/unity-engine/serialize-field.md) 属性を持つこと。
  * **ノート**: 場合によっては、`private` フィールドがシリアル化されます。詳しくは[ホットリロード](/engine/6000.0/manual/scripting/compilation-and-code-reload/script-serialization/how-unity-uses.md#hot-reload)を参照してください。

* `static` でないこと。

* `const` でないこと。

* `readonly` でないこと。

* シリアラル化可能なフィールド型であること。

  * プリミティブなデータ型 (int、float、double、bool、string など) であること。
  * Enum 型 (32 バイト以下) であること。
  * 固定サイズバッファであること。
  * Unity の組み込み型 (例えば、Vector2、Vector3、Rect、Matrix4x4、Color、AnimationCurve) であること。
  * Serializable 属性をもつカスタム構造体であること。
  * [UnityEngine.Object](/engine/6000.0/script-reference/unity-engine/object.md) から派生したオブジェクトを参照すること。
  * Serializable 属性を持つカスタムクラスであること。([カスタムクラスのシリアル化](#CustomClasses) を参照)。
  * 上記のフィールド型の配列であること。
  * 上記のフィールド型の `List<T>` であること。

**ノート**: Unity は、マルチレベルの型 (多次元配列、ジャグ配列、辞書、ネストされたコンテナタイプ) のシリアル化をサポートしていません。これらをシリアル化するには 2 つのオプションがあります。

* ネストされた型をクラスまたは構造体でラップする。
* [ISerializationCallbackReceiver](/engine/6000.0/script-reference/unity-engine/i-serialization-callback-receiver.md) を実装することにより、シリアル化コールバックを使用して、[カスタムのシリアル化](#CustomSerialization)を実行する。

## カスタムクラスのシリアル化##field-serialization-rules

Unity がカスタムクラスをシリアライズするためには、クラスが以下の状態であることが必要です。

* [Serializable](ScriptRef: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](/engine/6000.0/script-reference/unity-engine-serialization/managed-reference-utility/set-managed-reference-id-for-object.md) を参照してください。

**ノート**: インラインのシリアル化はより効率的なので、`[SerializeReference]` がサポートする機能の 1 つを特に必要としない限り、インラインのシリアル化を使用することをお勧めします。`[SerializeReference]` の使用方法の詳細は、[SerializeReference](/engine/6000.0/script-reference/unity-engine/serialize-reference.md) のドキュメントを参照してください。

## プロパティのシリアル化##scrollpoint-id=customclasses-/serialization-of-custom-classes

Unity では、以下のような場合を除き、通常プロパティをシリアル化することはありません。

* プロパティが明示的なバッキングフィールドを持つ場合、Unity は通常のシリアル化ルールに従ってそれをシリアル化します。 例:

```
public int MyInt
{
get => m_backing;
private set => m_backing = value;
}
[SerializeField] private int m_backing;
```

* Unity は、ホットリロード中にのみ、自動生成されたフィールドでプロパティをシリアル化します。

```lang-C#
public int MyInt { get; set; }
```

自動生成されたフィールドを持つプロパティを Unity にシリアル化させたくない場合は、`[field: NonSerialized]` 属性を使用します。

## 追加リソース##serialization-of-properties

* [カスタム製のシリアル化](/engine/6000.0/manual/scripting/compilation-and-code-reload/script-serialization/custom-serialization.md)
* [Unity がシリアル化を使用する方法](/engine/6000.0/manual/scripting/compilation-and-code-reload/script-serialization/how-unity-uses.md)
* [JSONSerialization](/engine/6000.0/manual/scripting/compilation-and-code-reload/script-serialization/json-serialization.md)
* [シリアル化エラー](/engine/6000.0/manual/scripting/compilation-and-code-reload/script-serialization/errors.md)
* [シリアル化のベストプラクティス](/engine/6000.0/manual/scripting/compilation-and-code-reload/script-serialization/best-practices.md)
