ドキュメント

Unity Engine

Unity Engine

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 は以下のようにスクリプトを再ロードします。
  1. ロードされたすべてのスクリプトのすべての変数をシリアル化して保存します。
  2. それらをシリアル化する前の元の値に復元します。
    • スクリプトをリロードすると、Unity は変数に
      [SerializeField]
      属性がなくても、シリアル化の要件を満たすすべての変数 (プライベート変数を含む) を復元します。例えば、スクリプトからリロードした後に参照を NULL にしたい場合など、private 変数を復元しないようにする必要がある場合があります。この場合は、
      [field: NonSerialized]
      属性を使用します。
    • Unity は決して静的変数を復元しないので、スクリプトを再ロードした後に保持する必要のある状態には静的変数を使用しないでください。再ロードプロセスでそれらが破棄されるためです。

プレハブ( Prefabs )

プレハブ は 1 つまたは複数の ゲームオブジェクト または コンポーネント のシリアル化されたデータです。プレハブインスタンスには、プレハブソースとその変更リストの両方への参照が含まれています。変更は、その特定のプレハブインスタンスを作成するために、プレハブソースに行う必要があります。
プレハブインスタンスは、Unity エディターでプロジェクトを編集している間だけ存在します。Unity エディターは、プレハブソースとプレハブインスタンスの変更の 2 つのシリアル化データからゲームオブジェクトをインスタンス化します。

インスタンス化

シーンに存在するすべてのもの (プレハブやゲームオブジェクトなど) で
Instantiate
を呼び出すと、以下が行われます。
  1. シリアル化を行います。これは、ランタイムとエディター内の両方で発生します。
    UnityEngine.Object
    から派生するものすべてをシリアル化することができます。
  2. 新しいゲームオブジェクトを作成し、データを新しいゲームオブジェクトにデシリアライズします。
  3. 同じシリアル化コードを異なるバリアントで実行し、他にどの
    UnityEngine.Objects
    が参照されているかをレポートします。すべての参照された
    UnityEngine.Objects
    を確認し、それらが Unity がインスタンス化したデータの一部であるかどうかを確認します。参照がテクスチャのような外部の何かを指している場合は、その参照をそのまま保持します。参照が子ゲームオブジェクトのような内部の何かを指している場合は、対応するコピーの参照を適用します。

使用しないアセットのアンロード

EditorUtility.UnloadUnusedAssetsImmediate
は Unity ネイティブのガベージコレクターであり、標準の C# ガベージ コレクターとは異なる目的を持ちます。シーンをロードした後に実行され、参照されなくなったオブジェクト (テクスチャなど) を確認して安全にアンロードします。Unity ネイティブのガベージコレクターは、オブジェクトが外部の
UnityEngine.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 ディレクティブ内でフィールドを宣言する場合など)。

追加リソース