見出し画像

VRChat初心者に贈る、Unityの親子関係・階層について

はじめに


VRChatで初めてUnityにふれた人にとって、理解しづらいものとして、Unityの親子関係・階層があると思っています。

そこで、この記事では出来るだけ噛み砕いて、Unityの親子関係・階層について解説しようと思います。初心者の人は是非読んでみてください。

[話を始める前に]
まだUnityを入手していない段階の人は、以下の記事の目次『コンポーネントとは?』まで(約2000字程度)を軽く読みつつ、導入してみてください。
導入方法の調べ方、Unityとは何なのか、そしてUnityの各ウィンドウがどのような役割を持っているのか、などが理解できると思います。

親子関係・階層について

Unityでは、左側のウィンドウはヒエラルキーという名前が付いています。

ここにはシーンと呼ばれる真ん中のウィンドウに配置した、様々な『ゲームオブジェクト』と呼ばれるアイテムの一覧が表示されています。

『ゲームオブジェクト』にはそれぞれコンポーネントというものを付けることで、色々な性質を持たせることが出来ますが、ここではその解説はしません。
(詳しくは上で貼ったコンポーネントの解説記事をご覧ください)

では、親子関係・階層の説明に移ります。

ヒエラルキーにあるゲームオブジェクトを長押しクリックで掴んで、他のゲームオブジェクトの上でクリックを離す(この操作は一般的にドラック&ドロップと呼ばれます。以後略します)と以下のようになります。

ドラック&ドロップしたオブジェクト名が一段下がっていることが分かるでしょうか?

一番上を1段目とするなら、今回操作したオブジェクトは2段目にいることになります。つまりこの二つのゲームオブジェクトは『階層』を形作っているわけです。

そしてこの時、上の階層にあるオブジェクトを親オブジェクト、下の階層にあるオブジェクトを子オブジェクトと呼びます。

つまりUnityにおける親子関係というのは、ゲームオブジェクトどうしの関係性を表した言葉になります。

家系図における家族関係のようなものだと考えると、一番分かりやすいかなと思います。

親に対して、子オブジェクトは無数にあっても大丈夫ですが、それぞれの子オブジェクトの直接の親は一つだけです。複数の親がいることはありません。
親の親……といったさらに上位があることはありますが、親の親と、親の関係性もまた、当然ながら親子関係です。

このように多くの階層がある場合もあります

何故この親子関係・階層というシステムが存在しているかというと、当然ながらそのほうが便利なことがあるからです。

(余談:一番上の親オブジェクトをルートオブジェクトと呼びます。ルートは日本語で『根』を意味するので、一番上の親オブジェクトが根っこ(ルート)なんだなと覚えておくと良いかもしれません)

親子関係・階層のメリット

Unityで親子関係にすることのメリットとして、一番大きいのは『親を移動させると、子も移動する』ことです。

例えばVRChatでよく使われているアバターは、服やアクセサリーといった沢山の小物を付けていることがあります。

もし親子関係の『親を移動させると、子も移動する』性質が無ければ、アバターが移動しても服やアクセサリーがその場に置いて行かれることになりますよね?

『親を移動させると、子も移動する』性質があると、一緒に持ち運びできますので非常に便利なわけです。

一方で、逆は違っていて『子を移動させても、親は移動しない』ので、子オブジェクトは好きに動かすことが出来つつ、親に追従します。

例えばアバターの髪飾りの位置を少し変えても、アバター自体が親オブジェクトであれば、きちんと追従してくれるわけです。

親オブジェクトと子オブジェクトを扱う時は、この二つの性質を理解しておくことが大事です。

親子関係の特性[相対性]

先ほどお話しした通り親子関係には『親を移動させると、子も移動する』特性があります。

これは子オブジェクトの位置が、親オブジェクトと相対的になっているからです……と言われてピンとくる人は少ないと思うので、詳しく説明したいと思います。

『ゲームオブジェクト』をヒエラルキー上で選択すると、右側のウィンドウであるインスペクターに、そのゲームオブジェクトの詳細が表示されます。

各ゲームオブジェクトには、そのゲームオブジェクトの位置・角度・大きさの情報を持つ、Transformコンポーネントが必ず付いています。

実はここが一番混乱するところかなと思っていますが、子オブジェクトのTransformコンポーネントの位置の値は、親オブジェクトのTransformの位置を基準(=原点)としたものになっています。

まだ分かりにくいと思うので、基本的なところから詳しく説明していきます。

まずTransformコンポーネントの位置(Position)は三つの値、(X,Y,Z)で表されています。

ようは三次元座標で位置が表現されているということなのですが、数学的な話はちょっと……って人は『左右方向にXメートル、前後方向にZメートル、上下方向にYメートル移動した場所』だと思ってください。
(それぞれ右、前、上がプラスの方向で、それぞれの逆方向はマイナスです)

三次元座標ということは、そのスタート地点(=原点)が存在するわけですが、一番上の階層の親オブジェクト達には共通の原点が存在します。

それはワールド座標(またはグローバル座標)と呼ばれていて、シーン画面上に1個だけ存在する絶対的な座標です。なので、一番上の階層にある親オブジェクト達のTransformの位置の値は、その絶対的な座標を基準としていますので、『絶対的』であると言えます。

一方で子オブジェクトについては違います。

自分の親となるオブジェクトの座標を基準としていますので、親と相対的な座標が自分のTransformの位置の値になっています。だから『相対的』です。
こちらは先ほどのグローバル座標に対応する形で、ローカル座標と呼ばれています(補足:グローバル=全体的な、ローカル=局所的な)

では具体的な例を挙げて、説明していきます。

まず分かりやすいように、ワールドの原点に赤い球のオブジェクトを置いておいた後に、一組の親子のゲームオブジェクトを作成しました。親を青、子を緑にしています。

親オブジェクトの位置を(X,Y,Z) = (2,0,0)にします。

仮に、子オブジェクトが親オブジェクトと全く同じ位置にあった時、その子オブジェクトの位置は(X,Y,Z) = (0,0,0)になります。親オブジェクトを基準とした座標になっているので、親と同じ位置にある場合は原点にある状態になるわけです。

では上の写真のようにワールドの原点を対象に、反対の位置に子オブジェクトを置いたとしましょう。

この場合の子オブジェクトの座標は(X,Y,Z) = (-4,0,0)になります。

親オブジェクトから見て、ワールドの原点は右に2mのところにあります。なので、親を基準にしている子オブジェクトの位置は(X,Y,Z) = (-4,0,0)になるというわけです。

これが混乱を招きやすいので、注意する必要があります。……が、考え方は簡単です。

『子オブジェクトは、自分の親オブジェクトを基準とする』と覚えておき、あとは親を基準にどっちの方向に移動させたいかを考えれば良いです。

とはいえ、Unity上では矢印マークを直接掴んで直感的に移動させることが出来ますので、気にする必要があるのは値の入力を直接行うときくらいです。

子オブジェクトを親オブジェクトの外にドラッグ&ドロップすると、親子関係を解除できます。

この時、子オブジェクトのTransformコンポーネントの値は、その時移動させた場所に応じて変化しますが、勝手にシーン上の位置や回転や大きさが変わるようなことはありません。

例えば上で例に挙げている子オブジェクトを、親子関係を解除し、一番上の階層に移動させると、子オブジェクトのTransformの値は(X,Y,Z) = (-2,0,0)になります。ですが、位置・回転・大きさは同じままです。

一番上の階層に移動したので、原点基準の値に自動的に書き換わったというわけです。値が変化して、『あれ!?』って思うかもしれませんが、Unity側が親切に変えてくれているだけです。

Transformの値はこのように相対的に変化するものなので、親オブジェクトのが基準になっているんだということを意識しておいたほうが良いでしょう。
一度分からなくなったら、親子関係を解除してみるのもありです。

注意:親の変更は子全てに波及する

例えば親のスケールを3倍にしたとき、子はどうなるかというと、子も3倍の大きさになります。

仮にアバターを丸ごと小さくしたいと思った時に、一番上の親を小さくすれば全て小さくなってくれる……など、便利な話ではありますが、意図していないもののサイズまで、小さくなっていることもあるので注意が必要です。

親だけ変更したい場合は一度、親子関係を解除して(つまり子オブジェクトを外側に全て出した状態で)編集を行い、それから子オブジェクトを再び戻してあげて、親子関係にしてあげると良いでしょう。

親子関係の相対性の利用方法

直接の親オブジェクトが基準となるというのは、ちょっとしたことで便利ですので、例を紹介しようと思います。

扉をはめようと思ったら縦にデカかった場合を考えてみます。
オブジェクトの基準位置は、3Dのモデルが作成された段階で、既に決まっています。
仮に中心位置が扉の真ん中にあった場合、Transformコンポーネントのスケールをいじっても以下のキューブのような伸び縮みの仕方をします。

これだと調整がとても難しいですよね?

そこで、親オブジェクトを作ることで調整を行いやすくしてみましょう。

先ほど親オブジェクトが子オブジェクトの基準になると説明しました。
なので、今回基準になってほしいところをまず考えてみますと、扉の下(もしくは上)の部分ですよね?

ヒエラルキーで右クリックを押し、Create Emptyをクリックすると空のゲームオブジェクトが生成されます。このオブジェクトをまずは基準にしたい位置に動かします。
今回は扉の左下に配置してみました。

そして、扉のゲームオブジェクトを先ほど作成したゲームオブジェクトの子にします。

左上の矢印の部分がPivotになっていることを確認してください。

この状態で親オブジェクトのスケールをいじると、以下のようになります。

子オブジェクトは親オブジェクト基準になっていますので、親のスケールを変えると基準がある下側はそのままで、上下に縮みます。

これで扉の大きさの調節がしやすくなりました。

また、扉なので開いたり閉じたりしてほしいですよね?

子オブジェクト単体で回転させると、中心位置が真ん中になっているので、中心を軸とした回転になってしまいます。

ここで先ほど設定した親オブジェクトで、Transformの回転の値を調整すると、きちんと扉のように回転してくれます。

親オブジェクトの位置が扉のこの部分にあるので、基準が左側になって回転してくれるということです。

これは色々な応用が利く話なので、是非覚えてみてください。

相対性を利用した値の直接入力


素朴な疑問として『直接操作できるのに、値の入力を直接行うことはあるの?』と思うかもしれませんが、いくつか便利なパターンがあります。

Unityのこの値を入力する欄というのは、ちょっとした数式をサポートしています。これがちょこっとしたオブジェクトの配置に便利です。

例えば5メートルごとにオブジェクトを並べたいと思った時、数値を打ち込んでいっても良いのですが、数式をコピー・ペーストするとお手軽にできます。具体的に説明していきましょう。

ここに1個のキューブがあります。これをX方向に5メートル間隔で複製・配置したいとします。手順は以下の動画で実演しています。

まず1個目のキューブを選択した状態で、[Ctrl]+[D]を押します。これは複製のショートカットですので、同じ位置にもう一個キューブが複製されます。

複製されたキューブが自動選択されていますので、TransformコンポーネントのXのところで+5と入力し、これを選択しコピーしておきます。無事コピー出来たらEnterキーを押すと、TransformのXは+5された値になり、複製されたキューブの位置は5メートル先にあります。

シーン画面で右クリックしながらドラッグで、視点を少し動かした後、もう一度[Ctrl]+[D]を押します
(先ほど移動させたキューブが選択済みなのですが、シーン画面で操作しないと[Ctrl]+[D]が効かないので、仕方なく視点移動を挟んでいます)

今度は+5メートル移動したキューブが複製されます。Xの値の後ろ側を2回クリック(1回だと上書きになるので注意)し、先ほどコピーした+5をペースト(貼り付け)し、Enterキーを押します。

これにより、もう一個キューブを並べることが出来ました。

あとは繰り返すだけで、綺麗に5メートル間隔で並んだキューブを作れるというわけです。

さて、では整列させたキューブをまとめて複製してみましょう。
手順は以下の動画で実演しています。

複数のオブジェクトを複製するときは親オブジェクトを作ると便利です。

なぜなら、親オブジェクト一つコピーすれば、子オブジェクトも全てまとめて複製されるからです。また、位置・回転・大きさを変更したい場合も親のTransformの値をいじるだけで済みます。

ではやってみましょう。右クリック、Create Emptyから空のゲームオブジェクトを生成します。これを親オブジェクトとします。念のためTransformの位置を(0,0,0)にしておきます。

一番上にあるキューブのゲームオブジェクトをクリックした後、Shiftキーを押しながら一番下のキューブのゲームオブジェクトをクリックすると、まとめて選択が出来ます。

この状態でドラック&ドロップすると、キューブ達をまとめて子オブジェクトにできます。

さて無事に親子関係を作れたので、親オブジェクトを選択し、複製してみましょう。あとは好きなように並べて行けばOKです。

これでまとめて複製できるようになったわけですが、折角綺麗に並んだキューブがあるのでもう少し遊んでみましょう。
一度複製した親オブジェクトを消して1個にします。これを原点を中心に、放射状に並べてみます。手順は以下の動画で実演しています。

原点を中心に回転させるにあたって、最初に作成したキューブがワールド原点にある場合、複製したときに重なってしまい不都合なので、親オブジェクトのXに1入力し、1メートルX方向にずらしておきます。
(動画ではその必要がなかったのでそのままやっています)

では、今度は30度ごとに回転させて、配置していってみると、放射状に並べることが出来ます。親オブジェクトが原点を基準としていることを利用しているというわけです。

このように、キューブを規則的に並べるだけでも結構面白いので、Unityの操作にまだ不慣れな人は、練習がてら是非遊んでみてください。

また上のキューブを並べる動画では、ショートカットを多用しています。

ショートカットを併用することで、効率よく作業することが出来ます。Unityの代表的なショートカットについては記事を書いているので、良かったら読んでみてください。

ちなみにこれの発展的な例としては、プログラムを使って同様以上のことがUnityでは出来ます。最近見たものを紹介すると、以下の記事とかですね。

ですが、あくまで先ほど紹介した操作が出来れば十二分だと思います。
基本的にアバターやワールドを作っている人でも、ここまでキューブを使い倒している人はほぼいないと思うので(どちらかというとモデリングとかシェーダーとかのほうが、色々出来るので頑張っている人のほうが多いです)

おわりに

Unityの親子関係・階層について色々説明しましたが、いかがだったでしょうか。

ここら辺をあまり知らなくても、何となくで利用できるのがUnityではありますが、知っていると効率よく作業が出来るはずです。

中々覚えることが多くて大変だと思いますが、少しずつでも良いので覚えていくと色々出来るようになってきて楽しいと思います。

では、ここまで読んでくれた勉強熱心な方に敬意を表しつつ、文章を締めさせていただきます。
読了お疲れ様でした。

この記事が気に入ったらサポートをしてみませんか?