Unity のシリアル化の使用方法
More details about how serialization works in Unity.
読み終わるまでの所要時間 12 分最終更新 1ヶ月前
保存とロード
Unity はシリアル化を使って シーン、アセット、アセットバンドル をデバイスのメモリに (または、メモリから) ロードして保存します。これには、独自のスクリプティング API オブジェクトに格納される MonoBehaviour コンポーネントや ScriptableObject などのデータも含まれます。
Unity エディターの機能の多くは、基軸となるシリアル化システム上に構築されています。シリアル化で特に気を付けるべき 2 つの点は Inspector ウィンドウ とホットリロードです。
Inspector ウィンドウ
Inspector ウィンドウには、表示中のオブジェクトのシリアル化されたフィールド値が表示されます。Inspector 内で値を変更すると、Inspector はシリアル化されたデータを更新し、デシリアライゼーションをトリガーして表示中のオブジェクトを更新します。
Unity のビルトインオブジェクトも、MonoBehaviour から派生したクラスなどのスクリプトオブジェクトも同様です。
Unity は、Inspector ウィンドウで値を表示したり変更したりする際に、C# のプロパティゲッターやセッターを一切呼び出しません。代わりに、Unity はシリアル化されたバッキングフィールドに直接アクセスします。
ホットリロード
スクリプトコードのホットリロードは、アセットデータベースの更新の一環として実行されます。ホットリロードとは、エディターの実行中に、再起動せずにコード変更を直接リロードして適用する処理を指します。詳細は、アセットデータベースの更新 と ホットリロード を参照してください。
ノート: ホットリロードはシリアル化の特殊なケースです。他のケースのシリアル化とは異なり、private フィールドは、 SerializeField 属性を持たなくても、リロード時にデフォルトでシリアル化されます。
Unity は以下のようにスクリプトを再ロードします。
-
ロードされたすべてのスクリプトのすべての変数をシリアル化して保存します。
-
それらをシリアル化する前の元の値に復元します。
- スクリプトをリロードすると、Unity は変数に 属性がなくても、シリアル化の要件を満たすすべての変数 (プライベート変数を含む) を復元します。例えば、スクリプトからリロードした後に参照を NULL にしたい場合など、private 変数を復元しないようにする必要がある場合があります。この場合は、
[SerializeField]属性を使用します。[field: NonSerialized] - Unity は決して静的変数を復元しないので、スクリプトを再ロードした後に保持する必要のある状態には静的変数を使用しないでください。再ロードプロセスでそれらが破棄されるためです。
- スクリプトをリロードすると、Unity は変数に
プレハブ( Prefabs )
プレハブ は 1 つまたは複数の ゲームオブジェクト または コンポーネント のシリアル化されたデータです。プレハブインスタンスには、プレハブソースとその変更リストの両方への参照が含まれています。変更は、その特定のプレハブインスタンスを作成するために、プレハブソースに行う必要があります。
プレハブインスタンスは、Unity エディターでプロジェクトを編集している間だけ存在します。Unity エディターは、プレハブソースとプレハブインスタンスの変更の 2 つのシリアル化データからゲームオブジェクトをインスタンス化します。
インスタンス化
シーンに存在するすべてのもの (プレハブやゲームオブジェクトなど) で を呼び出すと、以下が行われます。
Instantiate- シリアル化を行います。これは、ランタイムとエディター内の両方で発生します。から派生するものすべてをシリアル化することができます。
UnityEngine.Object - 新しいゲームオブジェクトを作成し、データを新しいゲームオブジェクトにデシリアライズします。
- 同じシリアル化コードを異なるバリアントで実行し、他にどの が参照されているかをレポートします。すべての参照された
UnityEngine.Objectsを確認し、それらが Unity がインスタンス化したデータの一部であるかどうかを確認します。参照がテクスチャのような外部の何かを指している場合は、その参照をそのまま保持します。参照が子ゲームオブジェクトのような内部の何かを指している場合は、対応するコピーの参照を適用します。UnityEngine.Objects
使用しないアセットのアンロード
EditorUtility.UnloadUnusedAssetsImmediateUnityEngine.Objectsエディターとランタイムのシリアライゼーションの違い
シリアル化のほとんどはエディターで行われ、デシリアライズはランタイムに集中して行われます。Unity は一部の機能をエディターでのみシリアル化しますが、他の機能はエディターとランタイムの両方でシリアル化できます。
機能 | Editor | ランタイム |
|---|---|---|
| バイナリ形式のアセット | 読み込み/書き込み対応 | 読み込み対応 |
| YAML 形式のアセット | 読み込み/書き込み対応 | サポートなし |
| シーン、プレハブ、その他のアセットの保存 | 再生モード以外でサポート | サポートなし |
| JsonUtility による個々のオブジェクトのシリアル化 | JsonUtility による読み込み/書き込みのサポート EditorJsonUtility による追加のオブジェクトタイプのサポート | JsonUtility による読み込み/書き込み対応 |
| SerializeReference | サポートあり | サポートあり |
| ISerializationCallbackReceiver | サポートあり | サポートあり |
| FormerlySerializedAs | サポートあり | サポートなし |
オブジェクトは、UNITY_EDITOR スクリプトシンボル 内でフィールドを宣言するときのように、エディターだけがシリアル化する追加フィールドを持つことができます。
public class SerializeRules : MonoBehaviour{#if UNITY_EDITORpublic int m_intEditorOnly;#endif}
この例では、 フィールドはエディターでのみシリアル化され、ビルドには含まれません。これにより、エディターでのみ必要なデータをビルドから省いてメモリを節約できます。そのフィールドを使用するコードも、例えば ブロックで条件付きコンパイルし、ビルド時にクラスがコンパイルできるようにする必要があります。
m_intEditorOnly#if UNITY_EDITORエディターは、Unity がランタイムにのみシリアライズするフィールドを持つオブジェクトをサポートしていません (例えば、UNITY_STANDALONE ディレクティブ内でフィールドを宣言する場合など)。