【Unity】Inspectorで値を変える時、publicとSerializeFieldどっち使う?
作成したスクリプトは多くの場合、ゲームオブジェクトにアタッチするかと思いますが、Inspectorウィンドウからメンバ変数の値を変えたいぜ!!
って時にはpublicにするか[SerializeField]をつけるか、なんてのが選択肢になります。
ふと思ったんですが、どっちをつける派が多いんでしょうかね。
それぞれ目的が異なるのでどっちが正解なんてのはないんですけど、用途を改めて整理したいと思います。
環境
macOS 10.13 High Sierra
Unity2018.1.0f2
Inspectorウィンドウから値を変える方法
スクリプトをアタッチした際、Inspectorウィンドウからメンバ変数の値を変えたいことがあります。
ゲームの実行中にInspectorウィンドウから動的に値を変えることができると、オブジェクトの位置や敵の強さなどのバランスを調整しやすくなります。
値を変えるたびにゲームを実行し直すのもなんだか大変ですし。
これを実現する方法として、Inspectorウィンドウから値を変えたいメンバ変数をpublicにする方法と、[SerializeField]をつける2通りの方法があります。
上のスクリプトをアタッチすると、Inspectorウィンドウでは以下のように表示されます。
publicにする
こちらはとても分かりやすい方法。
Unityではpublicなメンバ変数をシリアライズの対象にするので、Inspectorで値の確認・変更が可能になります。
シリアライズは、Unityがデータやオブジェクトの状態を保持してくれる仕組みのこと(ざっくり)
シリアライズする=Unityがメンバ変数の値を保持する=Inspectorから値を変えた時に保持してくれる、みたいなイメージ。
[SerializeField]をつける
この[]で囲っているのは、クラスやメンバ変数(フィールド)に特別な動作指示を与える属性(Attribute)です。
この[SerializeField]は「このフィールドをシリアライズしてください」という指示です。この方法でもInspectorから値を変えられるようになります。
publicとの違いは、他のスクリプトから対象のフィールドを操作できるかどうか、という点です。
publicなら他のスクリプトから直接値を変更できますが、[SerializeField]の場合はprivateなフィールドのままなので、他のスクリプトから値を変更できません。
下の画像はVSCodeでスクリプトを編集している画面ですが、外部のスクリプトからはprivateフィールドであるmpには値をセットできず、赤線でエラーが表示されています。
なお、publicの場合も[SerializeField]の場合も、Inspectorから値を変える時はダイレクトに値をいじるため、getter/setterが呼ばれません。プロパティをシリアライズするなら注意。
publicと[SerializeField]の使い分け
上でも少し触れましたが、使い分けのポイントは他のスクリプトから直接フィールドの値を操作するかどうかです。
publicなフィールドであればスクリプトをGetComponentした時に操作可能に。privateなフィールドに[SerializeField]をつけたときはGetComponentしてもいじれません。
オブジェクト指向的にフィールドは基本private、必要になったら仕方なくpublic、みたいなスタンスかと思うので、なるべく[SerializeField]で対応した方が良さげ。
publicにしちゃうと、外部から値を変えることができてしまうため、変な値が入ってきてもどこで変わったのか特定できなかったりと、結構めんどくさいんです。
ただ、Unityのマニュアルで『SerializeField』の項目を読むと、「多分君たちはこのAttributeを使う必要はほとんどないと思うよ。だってUnityはpublicなフィールドにすればシリアライズしてくれるからね(意訳)」と書かれているので、Unity的にはpublicにして欲しいっぽい。
実際、マニュアル内ではpublicで書かれているサンプルコードも多いように思います。分かりやすさで言ったら断然publicにする方ですし。
オブジェクト指向で考えてprivateに[SerializeField]をつけるか。Unityのマニュアルにしたがってpublicにしてしまうか。この辺はチーム内の開発方針で決めるのがいいかも。
まとめ
publicと[SerializeField]の使い分けのポイントは、そのフィールドに外部のスクリプトからアクセスするかどうかです。
フィールドにダイレクトに値をぶっこめる状態を減らすのであれば、[SerializeField]をうまく使っていけるといいかも。
ゲーム開発の攻略チャートを作りました!
-
前の記事
【Unity】ゴルフっぽいゲームを作るチュートリアルの紹介 2018.06.11
-
次の記事
【Unity】HideInInspectorとSerializeFieldの興味深い関係 2018.06.12
すごくわかりやすかったです。ありがとう。