次のようなインスペクターで設定できる値って、どのように保存されてるの?
これらの値は、バイナリデータやテキストデータなどに変換されてファイルに保存されるわ。
この変換処理のことをシリアライズ(またはシリアル化)と言うの。
MonoBehaviourスクリプトで定義したフィールドをインスペクターから設定できるようにしたい場合、次のようなコードを書くことがあるでしょう。
インスペクターから設定した内容は、シリアライズすることでアセットファイル等に保存されます。
シリアライズ対象のフィールドは、上記の書き方のように定義する必要がありますが、必ず設定できるようになる(=シリアライズできる)とは限らず、シリアライズできる条件が存在します。
本記事では、シーンやPrefabなどのインスペクターから設定した値がどのように保存されるかについて解説していきます。
目次 非表示
シリアライズとは
シリアライズとは直列化と訳され、複数の要素をある規則に従い一直線にデータを並べることを言います。
一直線に並べたデータはバイト列のバイナリデータだったりJSONのテキストデータだったりとまちまちです。
データをシリアライズすると、ファイルやデータベースなど、永続的なデータとして保存することができます。また、端末間のデータ通信なども可能になります。
シリアライズされたデータをプログラムから使用するためには、シリアライズとは逆の操作を行う必要があります。
これをデシリアライズと言います。
Unityにおけるシリアライズ
UnityにおけるシーンファイルやPrefabなどのアセット情報は、すべてシリアライズされてファイルに保存されます。
普段私たちが触るUnityプロジェクトとビルドして生成される実行ファイルとでは、シリアライズされるデータ形式が異なります。
Unityプロジェクトでのシリアライズ形式は、メニューのEdit->Project Settings->Editorの順に選択して表示される画面のAsset Serializationの設定値によって決まります。
Unity2019.3.0では、Force Textが初期設定されます。
これは、アセットをYAML
と呼ばれるテキスト形式でシリアライズする設定です。
複数人で開発するときは、テキスト形式でシリアライズした方が色々と都合が良くておススメだわ!
なお、実行ファイルにビルドされたあとは、上記設定に関係なくバイナリ形式にシリアライズされるようです。
バイナリ形式はテキスト形式と比べてシリアライズ/デシリアライズの処理が高速という利点があります。
フィールドがシリアライズされる条件
スクリプトで定義したフィールドがシリアライズされる条件は、公式リファレンスに記載されています。
以下の条件を満たすフィールドがシリアライズされます。
- publicまたは[SerializeField]属性が指定されている
- staticフィールドではない
- constフィールドではない
- readonlyフィールドではない
- シリアライズ可能な型である
具体的にスクリプトで確認してみましょう。
サンプル
シリアライズされる条件を確かめるためのサンプルスクリプトです。される/されないのどちらかはコメントに記載しています。
実行結果
期待通りの結果になりました!
シリアライズ無効とインスペクター非表示の違い
ここで一つ落とし穴があります。
フィールドがインスペクターに表示されないからと言って、必ずしもそれがシリアライズされないという訳ではない点です。
HideInInspector属性をフィールドに指定すると、シリアライズするしないに関係なくインスペクターから非表示になります。
System.NonSerialized属性を指定すると、シリアライズそのものがされなくなります。
参考:HideInInspector – Unity スクリプトリファレンス
参考:NonSerialized – Unity スクリプトリファレンス
サンプル
publicフィールドにHideInInspector属性を指定した場合の挙動確認用サンプルです。
実行結果
フィールドが一切インスペクターに表示されなくなります。
このとき、シーンファイルを覗いてみると、フィールドデータがシリアライズされていることが分かります。
HideInInspector属性は、シリアライズしたいがインスペクターから直接値を編集して欲しくない場合などに使うと良いでしょう。
また、System.NonSerialized属性を指定すると、シリアライズそのものが無効になります。
この場合もインスペクターには表示されません。
独自のシリアライズ/デシリアライズ処理を実装する
Unityでは、シリアライズ/デシリアライズのタイミングをフックする手段が提供されています。
これを用いて独自のシリアライズ/デシリアライズ処理を行うことが可能です。
これはISerializationCallbackReceiverインタフェースを継承して実現します。
参考:ISerializationCallbackReceiver – Unity スクリプトリファレンス
さっそく具体例を見ましょう。
サンプル
実行結果
例では、シリアライズするときはint型整数値にしておき、デシリアライズするときに文字列型に展開しています。
試しにInt Valueに値を入力すると、Str Valueに数字の文字列が入ります。
さいごに
インスペクターから設定したスクリプト情報は特定の形式でシリアライズされて保存されることが分かりました。
Unityにはもう一つメタファイルが存在しており、この中にも別のシリアライズされた設定情報が格納されています。
メタファイルの仕組みについては、以下記事をご覧ください。