VRChatterに向けた複数人でワールド制作のためのPrefab
概要
複数人でワールド制作を行う際に、Gitを使うことが多いと思います。
その際に、Prefabをどのように扱い方を知っている事で、制作をよりしやすく出来るようになることを願います。
対象読者
Worldをアップロードした事がある
Prefabは量産するためだけに使ってるくらいの認識の人
Gitは個人でのみ使っている人
ワールド制作チームでGitを使う事になった人
この記事を読んで目指すべき所
Prefabを作る時に、その粒度にする理由が説明できる
Gitを踏まえた上で、どういったものがPrefab化しておく必要があるかがわかる
この記事で取り扱わない事
Gitの使い方についての詳細
Gitを用いた、プロジェクトの共有の環境の構築について
Prefabとはそもそも何か?
PrefabはUnityにおける「同様の階層構造と設定を適用した」ひとまとまりのアセットのことを指します。
つまり、Prefab化をしている場合、同じPrefabの変更を容易にすることができます。
これによって「同じ設定」をしたボタンなどの変更をしたい際に、このPrefabだけの変更で、使っている同様のPrefabを使っているもの「全て」に変更が適用されます。
Prefab化していない場合、設定の変更を「手動」で全て見つけ出し、同じ変更をしなければいけません。これは、大きなコンテンツを作成している場合、その適用すべき箇所が膨大になるため、非常に困難且つ手間になります。
Prefabの利便性は、この変更が用意に適用しやすい部分にあります。
また、このPrefabの概念の派生として、「PrefabVarient」と「PrefabNested」というものがあります。
最初は理解が大変かもしれないですが、理解するとワールドを作成するのが一段やりやすくなるので、ぜひ覚えていきましょう。
PrefabVarientについて
Prefabを語る上で欠かせないのが、このPrefabVarientです。
PrefabVarientは作成したPrefabから、一部の設定を変更したPrefabの事を指します。
以下は、Aという画像とインタラクトを設定したPrefabから、画像だけを変更したPrefabを作った
PrefabVarientの例です。
![](https://assets.st-note.com/img/1700407519574-BNsD1O5iOQ.png?width=1200)
このPrefabVarientの特徴は、特定のPrefabからの「差分」を変更したPrefabという事です。
そのため、元Prefabであるもので、「差分」に含まれていない変更に関しては、元Prefabの変更を適用されるといった特徴を持っています。
これはつまるところ以下のようなイメージを持っていただけるとあっているかと思います。
![](https://assets.st-note.com/img/1700407568238-bjfJ6ylRzW.png?width=1200)
上記の例では、PrefabAに画像とテキストのコンポーネントが付いている状態で、そこからPrefabVarientとして、PrefabA’を作成し、そちらは、テキストを変更したものです。
この状態で、PrefabAの方の画像、テキストの値などの内容を変更した場合、PrefabA‘には、画像だけが適用されます。
PrefabNestedについて
PrefabNesterdは、Prefabの中に別のPrefabが存在する状態の事を指します。
イメージでいうと以下の感じです。
![](https://assets.st-note.com/img/1700407634133-vDagRgImwb.png?width=1200)
これ以降、この章では、包んでいる側のPrefabAを親Prefab、その中にあるPrefabBを子Prefabとして呼称していきます。
これについて気をつける事としては、親Prefabから見た時に子Prefabの情報はPrefabVarientと同等の扱いになるという事です。
例えば以下のような感じです。
![](https://assets.st-note.com/img/1700407666982-3rP1mf4fK9.png)
上記は、親Prefabでの編集から子Prefabに該当する箇所のなんかしらの変更をした場面です。
この場合、これ以降、親Prefabの編集で変更した内容は、子Prefabでの編集で変更をしたとしても、更新される事はありません。
Prefab分割の粒度について
Prefabにおいて、頭を悩ませるのが、どれくらいの範囲でPrefab化していけばいいかというPrafabの粒度です。
全てを事細かにPrefabに分けた方がいいのか、一つそれなりの大きさにまとめればいいのか、はたまた、別の基準があるのか?と悩むことがあるかもしれません。
もちろん正確な回答で言えばケースによるとしか言えないです。
なのであくまでもVRCのワールド制作におけるPrefabの分ける私なりの基準ですが紹介します。
※実際のUnityのアプリ開発などでは別の基準になる可能性があることをご注意してください。
Prefab化しておいた方が良いなと思う目安
複数個所で、同様のものが使われる可能性があるもの
Scene上で一塊で動かしたいもの
(単体機能Prefabのプログラムの適用として、そのPrefabだけで終わらない場合)
Gitを使う際のSceneの影響が出るであろう範囲
それぞれ、詳しく見ていきましょう
複数個所で、同様のものが使われる可能性があるもの
具体的には、どういったものか?というと、VR空間内でのプレイヤーが触るボタンや、装置などがそれにあたります。
これは、最初に説明をしたPrababの利便性の部分を意識しての分割です。
また、一度作っておくと、別の場所で、同様のものが必要になった際も、それを使用するだけで終わり、適用も同様になります。
Scene上で一塊で動かしたいもの
これは、用意されているアセットが、細かく分割されている場合などによく使います。
例えば、家の扉などの場合でも、以下のように一つ一つGameObjectに分かれていた場合
右扉
左扉
右取っ手
左取っ手
ドアの枠組み(上下左右4パーツ)
となった場合、合計8つのGameObjectからドアが構成される事になります。
そのため、私がよくやっている事としては、これらの一つ上に空のGameObjectを追加して、その上で、Prefab化するという事をしています。
イメージで言うと下記画像のような感じです。DoorRootが、空のGameObjectに当たります。
![](https://assets.st-note.com/img/1700407789366-BCAw25m39X.png?width=1200)
また、こうしておくことで、ドアが必要になったら、このPrefabを追加するだけで、ドアが追加する事が出来るし、パーツの欠けや、隙間などもこのPrefabだけを修正すれば全てが修正されるので大変便利です。
(単体機能Prefabのプログラムの適用として、そのPrefabだけで終わらない場合)
個人的には、こちらの用途で、使用する事がほとんどです。
Udonプログラムにおいて、別のプログラムコードとを関連付ける事になります、
今回のこのケースは、この関連付けの変更を維持するためにPrefab化しています。
ただ、この関連付けの際に、その関連付けるもの同士が、Hierarchy上でまとまらない状態になっている場合がたびたび起こります。
その場合は、Prefab化する前に、プログラム側の処理を変えた方がいい場合があります。
Gitを使う際のScene上のコンフリクトを避けるためには?
色々ややこしい話がでてくるので、結論だけ先に書いておきます。
コンフリクトを発生させないために、「Prefab化」を「適切に」行い、Sceneの変更を起こさないようする。
そもそも、コンフリクトの説明を、超ざっくり説明すると、並行して作業を行い、その際同様のファイルを変更した場合に、どっちの変更が正しいんだ?となっている状態を指します。
これはテキストファイルなどの文字ベースだと、問題ないのですが、今回注目している.sceneファイルや、.prefabファイルのファイルだと、その正しいんだの判断が付けれない事の方が99%くらいです。
なので、このコンフリクトの事を意識せずに、Gitを使っている方だと、コンフリクトが非常に発生します。
このコンフリクトが発生すると、そのファイルに関連する変更を、「その変更をしていた誰か一人」のみを適用して、残りの人達は再度同じ作業をするはめになります。
そのため、これをきっかけでぎくしゃくすることになります。
なので、ちゃんと理解した上で、発生させないようにしなければいけません。
そして、このコンフリクトが発生しやすいファイルのひとつとして.sceneファイルが候補として上がります。
何故か?
それは、この.sceneファイルが変更される操作として
「Scene上で」GameObject(Prefab含む)に対しての変更をした時
LightやRenderingの設定を変更した時
に、変更されます。
要はHierarchy上で行う操作はSceneの変更につながります。
しかしながら、Prefab化する事で、これらの変更が発生しなくなります。
詳細は、別コラムで作っているので、ここではざっくりの説明をすると、Prefab化する事によって、Scene上でそのPrefabの操作をしない限りは、Prefab内だけの変化であり、変化が起きるのはあくまでもPrefabだけで済むためです。
ただ、これは、あくまでもすでにHierarchy上に置いてあるPrefabのみを指すので、新たにPrefabなどを置く場合は、ほぼほぼSceneの変更になります。
そのため、基本的には、Prefab化した後は、適切なPrefab内での変更するだけにとどめておくことが良いでしょう。
これの最大のメリットは、同じSceneの中でもPrefabさえあれば、並行作業を進める事が出来るという事です。
Aさんが、Scene内に配置されているAPrefabというPrefabに対して作業を行い
Bさんが、Scene内に配置されているBPrefabというPrefabに対して作業を行う
といった具合で、並行して作業を進める事が出来ます。
なので、ちゃんと適切な粒度で、Prefab化しようねというお話でした。
おまけ
ここでは、実際のSceneファイルが、ざっくりどういった情報持っているか、GameObjectをPrefab化する事でどういった変化が起きているかを深ぼっています。
より理解をするために、Sceneファイルというものがどういった情報を持っているかをしらなければなりません。
Sceneは.sceneの拡張子のファイルで管理されています。
.sceneは様々な情報を持っています。
Lightの設定
Renderingの設定
GameObjectが持っている情報
コンポーネントのGUID
スクリプトなど
例えば、以下の内容がHierarchy上に何もない状態の純粋なSceneだけの情報です。
![](https://assets.st-note.com/img/1700408034584-qlOqiRIwAy.png?width=1200)
これでもまだ途中のものを抜粋してきました。
ここに空のGameObejctを追加するとこういった感じの差分が出ます。
GameObject自身と、
![](https://assets.st-note.com/img/1700408070341-vYRlz94iVv.png)
ここでは、GameObject自身とTransformというものを持っている事がわかります。
この空のオブジェクトをPrefab化した時のScene情報が以下の通りです。
赤が、従来のGameObejctの時の情報、緑が、置き換わった部分
![](https://assets.st-note.com/img/1700408106853-IwzQd8nmmw.png)
![](https://assets.st-note.com/img/1700408122071-pnu6DJMdRS.png)
何が起きているのでしょうか?
具体的に何が起きていると断言はできないですが、Scene上では、おおよそ以下の感じに置き換わっているのではないかな?と思われます。
GameObjectだった時
全ての情報をScene上が管理する必要があり、変更はSceneの変更につながる
Prefabする事によって起きたこと
Scene上で管理するのは、「Prefabがどれか」「具体的な差分」
これによって、Prefab上で値を変更している限りは、Scene上では差分が出ない状態になります。