前回プレハブの基本について解説しました。
今回はプレハブのちょっと発展した使い方を解説したいと思います。↑の動画でも解説していますので、ぜひご活用ください。動画はUnity2018.3以降のバージョンについて解説しています。
この記事は本のように順を追って解説しています。この記事は途中のページになります。
この記事を見ていて、現在の状況がわからない場合や忘れてしまった事などが出てきたら↓のリンクから目次ページへ飛べますので立ち戻って見てください。
<プレハブの親子関係>
プレハブは実は子オブジェクトを含めることができます。親オブジェクトをプレハブ化すると、子オブジェクトも含まれた状態でプレハブ化します。
子オブジェクトがある状態でプレハブ化すると

↑のように、子オブジェクトが青色の文字になってプレハブに含まれている事がわかります。
子オブジェクトがプレハブに含まれている場合の注意点
Unity2018.3以降のバージョンの場合、子オブジェクトが含まれているプレハブに新たにゲームオブジェクトをドラッグ&ドロップすると

するとエラーになります。

子オブジェクトをいじるならプレハブモードでやれと言われていますね。
一見、プレハブにしてしまったゲームオブジェクトには新たに子オブジェクトを追加できないように思えますが・・・

↑の位置にドラッグ&ドロップすると追加することができます。
非常にわかりづらいのですが、青色になっているオブジェクト同士の間に新たに子オブジェクトを追加することができません。
エラーでの警告文は今追加しようとしている子オブジェクトに対してではなく、既に存在している子オブジェクトの位置がズレてしまうのでプレハブモードで編集しろと言われているわけです。
とてもややこしい。
プレハブに子オブジェクトを追加するとプラスマークがついて、そのゲームオブジェクト独自の変更として扱われます。

これらはoverrides>Apply Allでプレハブに含めることができます。

<個別変更の適用>
Unity2018.3以降のバージョンの場合、プレハブから作ったゲームオブジェクトに独自の変更を加えるとoverridesからのApply Allで全ての変更をプレハブに適用することができますが、実は変更1個1個を個別に適用することもできます。
コンポーネントの適用について
プレハブを複製したゲームオブジェクトのコンポーネントをつけたり外したりすると

↑のように➖と+で表されます。
変更が存在する状態でコンポーネントの右側の歯車のようなマークをクリックすると↓のようになります。

このAdded Componentの項目で、どのプレハブに適用するのか選ぶことができます。変更を破棄することもできます。
この項目で選んだ場合、歯車マークを押したコンポーネント単体の変更だけが適用されます。
パラメーターの変更を適用
コンポーネントのパラメーターを変更した場合は、コンポーネントの右上の三点からModified Component >Apply to Prefabで

パラメーターの変更だけをプレハブに適用することができます。
子オブジェクトの追加を適用
コンポーネントの時のようにどのプレハブに適用するのかというのは子オブジェクトも選ぶ事ができます。追加した子オブジェクトで右クリックして、Added GameObject

すると、このようにどのプレハブに適用するのかを選ぶ事ができます。これは現在選択している子オブジェクトのみに適用されます。
<Cannot restructure Prefab instance>
また、プレハブの中に子オブジェクトを入れて適用すると、プレハブ画面でしかいじれないようになります。
プレハブモードではない状態でヒエラルキーから子オブジェクトを削除したり、親子関係を解除しようとしたりすると、

このようなダイアログが表示されて、子オブジェクトを動かせないようになります。Unity2018.3以降のバージョンではプレハブ内の親子関係をいじる際は、新しい子オブジェクトを追加する以外の行動は取れないので、プレハブモードで修正する必要があります。
プレハブモードの細かい使い方については↓の記事にまとめてみたので、興味のある方はのぞいてみて下さい。
<Nested Prefabsとは>
プレハブには「入れ子」と呼ばれる状態があります。
どういう状態かと言うと、プレハブの中に別のプレハブが存在すると言う場合です。
これをネステッドプレハブと言います。
Unity2018.3より前かそれ以降かで扱いが違うので注意してください。Unity2018.3より前のバージョンの使い方はコチラへ飛んでください
Nested Prefabsの使い方
Unity2018.3以降のバージョンの場合、プレハブの中にプレハブを入れることができます。この機能の事をNested Prefabsと言います。
とりあえずやってみましょう。前回用意した適当に作ったプレハブをとりあえずシーン上に置いてみます。

とりあえず、これを3つくらい並べてみましょうか

とりあえず、並べました。それではこれらとは別のプレハブを作ってみましょう。

とりあえず、Sphereを作ってプレハブにしてみました。

ここで、真ん中の棒をSphereの子オブジェクトにします。
ちょっと、これではわかりづらいので、もう一個適当にオブジェクトを作って、今度はプレハブにはせずにSphereの子オブジェクトにしてみましょう。

Capsuleというオブジェクトを作成して、Sphereの子オブジェクトにしてみました。すると、Cubeのアイコンは青色なのに、Capsuleは白色です。
プレハブを元にして作られたゲームオブジェクトは青色の箱で見分けがつくようになっています。Cubeはプレハブですが、Capsuleはプレハブではないということですね。
このように、「プレハブを元にして作られたゲームオブジェクト」の中に「プレハブを元にして作られたゲームオブジェクト」を入れても、プレハブとの関係が維持されているのがわかります。
これがプレハブの入れ子状態です。
この状態で、Apply Allを押してみましょう。

これで、プレハブの中にプレハブが入っている状態になりました。
ヒエラルキーを見ても、ちゃんと子オブジェクトが青字になっているのがわかります。

青字になってSphereのプレハブに含まれている事がわかるし、横の箱の色で、その子オブジェクト自体にもプレハブがあるのかどうかがわかります。
この状態でCubeのプレハブをいじるとどうなるのでしょうか。ちょっとやってみましょう。

さて、元のCubeのプレハブに対して変更を行ったところ、Sphereの中のプレハブには変更が反映されていない事がわかります。ただしこれは、Unityのバージョンによって挙動が変わる?みたいなので気を付けてください
プレハブの中にプレハブを入れた場合、そのプレハブは独自のパラメータを持っている物として扱われます。
独自のパラメータを持っているとして扱われている場合、プレハブの元ファイルを変更してもそのパラメータは適用されません。これは前回解説しています。
ちょっとややこしいですが、ヒエラルキー上でSphereの中のCubeを選択しても太字の場所はどこにもなく、独自のパラメータを持っているようには見えません。

ここでSphereの「>」をクリックして、Sphereのプレハブの画面に飛ぶと、↓のようにプレハブ用の画面ではパラメータに変更がされている事がわかります。

これは、ヒエラルキーにいるSphereの中のCubeはShpereのプレハブとパラメータが一致しているので変更はないものとして扱われます。
プレハブ画面のSphereの中のCubeは元のCubeのプレハブとパラメータが違うため、独自のパラメータを持っているものとして扱われるわけです。
元のプレハブと同じ状態にしたい場合は、プレハブ画面で

Cubeを選択した状態でRevert Allを押せば、Cubeの独自変更がなかったことになるので、

他のゲームオブジェクトと同じになります。
なんか大きさが違うのは親オブジェクトであるShpereのScaleが大きいからです。
逆にApply Allを押すことによって、入れ子にしたプレハブの変更を元のプレハブに適用することもできます。
Cyclic nesting detected
プレハブの中にプレハブを入れられることはわかりましたが、プレハブAの中にプレハブBを入れてApplyし、その後、プレハブBの中にプレハブAを入れてApplyするとどうなるでしょう。
要はお互いをループさせるようにプレハブを作るということです。

Cubeの中にSphereを入れてその中にCubeが入っている状態にしてみました。
Cubeの中にCubeが入っているので、上のCubeを更新すると下のCubeにも反映されて無限ループ状態になってしまいますね。
この状態でApply Allを押してみましょう。

コンソールにエラーが表示されました。このようにプレハブがループする形にはできないということですね。プレハブ画面で同じようなことをすると

このようなダイアログが出てきてできないようになっています。
Unity2018.3より前の場合
Unity2018.3より前のバージョンの場合、このプレハブの中にプレハブを入れてしまうと、入れた方のプレハブは入れられたプレハブの物になってしまうという習性があります。

とりあえず、前回適当に作ったプレハブをシーン上に置いてみました。
同じものを3つ並べてみましょうか。

とりあえず、並べました。それではこれらとは別のプレハブを作ってみましょう。

とりあえず、Sphereを作ってプレハブにしてみました。

ここで、真ん中の棒をSphereの子オブジェクトにします。

そして、SphereのApplyを押せば、SphereのプレハブはCubeのプレハブを含むことになるのですが、Unity2018.3より前の場合は、CubeはSphereに吸収されてしまいます。

↑のようにSphereの中にCubeがいるプレハブができます。
↓のように新しいプレハブに吸収されてしまった場合、元のプレハブを操作しても変更が反映されません。

Sphereの中のCubeの変更をRevertしても状態は変わりません。
<Prefab Variantsとは>
プレハブを用意したものの、そこからたくさん派生したい時というものもあると思います。
例えば、色違いの敵など、1つのものを基準としてそれとはちょっと違うプレハブを何種類も用意したい時はよくあります。
このように、1つのプレハブを基準に様々な派生として作られたプレハブをプレハブバリアントと言います。
これはUnity2018.3以降の機能なのでご注意ください。
Prefab Variantsの作り方
プロジェクトウィンドウでプレハブを選択した状態で右クリック>Create>Prefab Variant

すると↓のような派生系のプレハブを作成する事ができます。作成されたプレハブは初期の状態だと元のプレハブと同じ状態になっています。

この操作はヒエラルキーにあるプレハブからプロジェクトウィンドウにドラッグ&ドロップしても同じ事ができます。

↑のようにドラッグ&ドロップした際に
・Prefab Variant・・・派生系のプレハブにするのか
・Cancel・・・キャンセルするか
・Original Prefab・・・全く別のただのプレハブを作成するのか
というダイアログが表示されます。ここでPrefab Variantを選択すれば同じ事ができます。
Prefab Variantの変更について
このプレハブヴァリアントの機能を使用すると、派生元のプレハブを弄ると派生先のプレハブにも変更が適用されますが、派生先のプレハブをいじっても派生元には変更が反映されません。
この機能のおかげで、元々のプレハブを変更さえすれば、派生先にいちいち変更を適用する作業をしなくても大丈夫です。便利なので覚えておくといいと思いますよ。
ちなみに、派生先のプレハブの変更を元のプレハブに適用したいときは、プレハブ画面で一番上の親オブジェクトを選択し、Overrides>Apply All to BaseとすればOKです。

<まとめ>
・プレハブは親子関係を含める事ができるよ!
・親子関係を持ったプレハブの変更は新たに子オブジェクトを含めることはできるけど、移動、削除はプレハブモードじゃないとできないよ!
・プレハブからの独自変更は個別に適応できるよ!
・プレハブの中にプレハブを入れる事ができるよ!
・プレハブは派生系を作る事ができるよ!
さて、Unityについて色々学んで来ましたが、次回はUnityを使用する際の注意点について解説したいと思いますので、よろしくお願い致します。