【Unity】シリアライズされたフィールドの値はどこにあるの?

【Unity】シリアライズされたフィールドの値はどこにあるの?

ゲームオブジェクトにアタッチするスクリプトでは、publicや[SerializeField]を付けたフィールドはInspectorウィンドウから値を入力することができます。

ここで入力した値はUnityエディタを再起動した時にも保存されているのですが、一体どこに書かれているの? とふと疑問に思ったので調べてみました。

実は、みんながよく目にするあのファイルに……。

 

環境

macOS 10.14 Mojave

Unity2018.2.20f1

シリアライズとデシリアライズ

[SerializeField]に「シリアライズ」の言葉が含まれていますが、シリアライズデシリアライズについてちょっとおさらい。

シリアライズとは、メモリ上に展開しているデータ(オブジェクト)をひとまとまりの文字列なりバイト列に変換すること。もっと言えばそれをファイルなどに書き込んだりすることです。

Unityでシリアライズというとファイルに書き込むことを指していると考えて良さそう。

デシリアライズは逆にひとまとまりの文字列なりバイト列に変換されていたものをメモリ上に展開すること。シリアライズの対義語になっています。

シリアライズはメモリ上のオブジェクトをファイルに書き込んで保存すること、デシリアライズはファイルから読み込んだオブジェクトをメモリ上に展開すること、こんな感じです(ざっくり)

publicまたは[SerializeField]のフィールド

通常、C#のプログラムでフィールドをpublicにしたとしても、プログラムの実行が終了した後に再開したら初期値に戻っています。

Unityでpublicまたは[SerializeField]のAttributeが付いたフィールドの値が保持されているのは、Unityが独自に値を持ってくれているからなんです。

上記のマニュアルに書かれているUnityの仕様では、publicなフィールドと[SerializeField]のAttributeが付いたフィールドなどをシリアライズの対象としています。つまり、これらのフィールドの値はUnityがどこかのファイルに書き込んでいるはず。

シーン内に同じスクリプトをアタッチしたゲームオブジェクトがいても、それぞれで個別に値を持っているので、ゲームオブジェクトの情報が書かれたファイルがいるはずです。それは……。

答えはSceneファイルでした

うん、多分みんな分かっていたと思うけど、Sceneファイルに書かれています。

Sceneファイルはバイナリ形式またはテキスト形式で保存することができ、デフォルトではテキスト形式で保存されるようになっています。テキスト形式で保存しているメリットは、バージョン管理ソフトで差分を追いやすくなること。逆にバイナリ形式で保存する場合のメリットはディスク上のサイズが小さくて済むことです。

テキスト形式で保存される場合はYAML形式で記述され、シリアライズされたデータが記載されています。

その中に各ゲームオブジェクトについてシリアライズ対象フィールドの値が記載されます。

 

実際に見てみよう

確認のため以下のスクリプトを作成しました。

フィールドだけ持たせたシンプルなスクリプトです。これをゲームオブジェクトにアタッチし、任意の値を入力します。

privateなフィールドはシリアライズの対象ではないため、Inspectorウィンドウに表示されません。

Inspectorウィンドウで値を入力
Inspectorウィンドウで値を入力

 

この状態でシーンを保存した時に、Sceneファイルの中にmaxHpの値が記載されず、atkが5、defが8と記載されていることを確認します。

SceneファイルはVSCodeなどで開きます。すると以下の記述を見つけました。

Sceneファイルではゲームオブジェクトごと、コンポーネントごとに分けて記載されます。この中の「m_EditorClassIdentifier:」を見ると、ちゃんとatkが5、defが8として記録されていますね。シリアライズ対象とならないprivateなフィールドのmaxHpは記載されていません。

という訳でシリアライズ対象フィールドに対してInspectorウィンドウで入力した値はSceneファイルに記録されます。

外から編集できるかな

正体が分かると実験してみたくなるのがいきもののサガ。

テキストエディタからSceneファイルをいじってみます。変更する箇所はさっきと同じスクリプトのatk部分。これを99に変更してみましょ。

ファイルを保存してUnityに戻ると以下のダイアログが表示されました。シーンを開きっぱなしだとこのような通知をしてくれるみたい。実験なのでここは勇気を出して[Reload]をクリック。

変更を反映してリロードか無視か
変更を反映してリロードか無視か

 

再度シーンが読み込まれるので、変更した箇所を確認してみます。

外部からパワーをもらった
外部からパワーをもらった

 

テキストエディタで編集した通り、atkの値が99に変更されました。

Unityエディタを使わずにシーンを編集することも手段としては可能なので、Unityエディタ縛りでゲーム作成がしたい方はぜひ。

私は絶対やりません。

まとめ

初心者の頃から疑問に思っていた、シリアライズされたフィールドの値の行方、やっと解決しました。

Sceneファイルだったんですね。

ここでは実験のため外部からテキストエディタを使ってSceneファイルを編集しましたが、当然のことながらバグの温床になるため、良い子は真似しちゃダメよ。

アセット作ってます!

CTA-IMAGE

Unityでの開発に役立つアセットを作っています。

3DダンジョンRPGを開発するスピードを200%加速するAssetや、ファンタジーRPGのダンジョンを彩るパーツを取り揃えています。

特に3DダンジョンRPGのゲームを1から作るのは結構時間がかかります。ダンジョン部分の作成はこうしたアセットを使って、開発をブーストさせてみませんか?