UnityでVRゲーム製作!XR Interaction Toolkit ソケットにはめる編
どうも皆様 Hello world!
Unityでゲームを作っております、天野スズランと申します。
Unityの「XR Interaction Toolkit」でVR開発をする方法を書いていきたいなぁと思ってますので、皆様どうかお付き合いください。
今回やること
今回は、ソケットに対し、手に持っているアイテムをはめられるようにしていきたいなと思います。
ただ、そう言われてもイメージつきにくいですよね。
なのでもうちょっと具体的に、バッテリーをソケットにはめることを目的にしてみます。
なお、この記事は物を持つ編を見ていることが前提となります。
まだ見ていない方は、そちらもご覧ください。
アセットをインポート
今回は無料アセットを一つ使わせてもらっています。
「SCI-FI Barrels 40 Sample」というもので、カジュアルな SF っぽい感じの筒のアセットです。
それをはめる用のソケットもついてくるので、今回はそれを使わせてもらいます。インポートしておいてください。
バッテリーを作る
では、さっそく作っていきましょう。
まずは、バッテリーから。
バッテリーの配置
今回はインポートしたアセットの「Barrel_StandardS」をバッテリーに見立てようかと思います。
え?乾電池の方が形が近いって?まあ誤差です誤差。
Assets -> SCI-FI_Barrels_40 -> Sample にありますので、Hierarchy 上にドラッグアンドドロップします。
名前を「Battery」に変えておくと分かり易いと思います。
倍率の変更
しかしこのバッテリー、かなりデカいです。1mくらいあります。
なので、持ちやすいよう、Scale を 0.2 くらいにしておきましょう。
Inspector -> Transform で設定可能です。
持てるようにする
配置できたら、次は手で持てるようにしておきましょう。
上記の記事を参考に、XRGrabInteractable などを設定してみてください。
なお、当たり判定に関しては Sphere Collider より Capsule Collider を使った方が形を合わせやすいかと思います。
持つ位置の変更
また、初期状態だとバッテリーの底の方を持ってしまって操作しにくいので、持つ位置を変えておきましょう。
新しくBattery の子供に空のオブジェクトを作ります。
名前は「GrabPos」と付けておきました。
そして、その GrabPos をバッテリーの中央に移動しておきます。
Position の Y を 0.5 にしておくと丁度良い感じです。
そして、その GrabPos を XR Grab Interactable の Attach Transform に設定すると、持った時の位置を変えられます。
ソケットを置く
次に、バッテリーをセットするソケットを作っていきます。
配置
インポートしたアセット内に丁度良いオブジェクトがあるので、それを使いましょう。
_SCI-FI_Barrels_40_Sample -> Prefabs にある、「Barrel_HolderS」を、Hierarchy 上にドラッグアンドドロップします。
分かり易いよう、名前を「Socket」に変えてあります。
倍率指定と位置
それから、バッテリーと同様こちらも大きすぎるので、Scale を 0.2 にしておきます。
場所は、まあとりあえずバッテリーの隣にでも置いておきましょう。
私は、 Box を作ってその上に配置してみました。
バッテリーをはめられるようにする
次は、ソケットをソケットとして機能するようにしていきます。
なお、以下でやり方を解説してますが、手の時と大体同じです。
ソケットが手のようになっていて、何かを持つことができる、と考えると、イメージがつきやすいかもしれないです。
まず、Socket オブジェクトに、「XR Socket Interactor」をアタッチします。
Add Component から Socket とでも検索すれば出てきます。
次に、当たり判定を追加します。
この当たり判定の範囲が、Socket が物を持つ範囲となります。
まず Add Component から、Box Collider をアタッチしましょう。
そして、Is Trigger のチェックを付けます。
次に、サイズを調整します。
多分最初から Socket の大きさになってると思いますが、なっていない場合は調整しましょう。
Inspector の Edit Collider と書いてある横の ボタンを押すと、コライダーが調整できます。
持つ位置を変更する
これで、ソケットにバッテリーが付くようにはなりました。
が、バッテリーは、持つ位置を変更してますよね。
なので、持つ位置と持たれる位置が合わなくなっています。
Battery でやったように、Socket でも持つ位置を調整しましょう。
Socket の子供に空のオブジェクトを作りました。名前は「GrabPos」と付けてみました。
位置は、やはり真ん中あたり。
具体的には、Y = 0.5 にしてみました。
そして、その GrabPos を、Inspector の Attachi Transform に設定します。
そうすることで、以下のように丁度良い位置にはまってくれるはずです。
ランプを光らせる
これで、ソケットにはめることはできたのですが、はめられるだけです。
ゲームに出しても、だから何だと言われてしまいますから、ちゃんと動作するようにしてみましょう。
その目標として、ランプを光らせてみます。
応用すれば、ドアを開くとか、ドアを開けるとか…あと思いつかないですけど、ドアを開放するとかできると思います。
ランプオブジェクトの準備
まず、ランプオブジェクトを用意します。
といっても、Light コンポーネントで光らせてもめんどくさいわかりにくいので、黒い球体が赤くなる程度のものを目指します。
まず、明るい状態のランプを用意していきます。
Hierarchy 上で右クリックし、3D Object -> Sphere を選択することで、球体を作ります。
名前を RedSphere としておきました。
その球体の Transform の Scale を操作し、程よい大きさにしておきます。
私は、X,Y,Z それぞれに 0.1 を入れてみました。
それから、Project タブ上で右クリックし、Create -> Material でマテリアルを作ります。
そして、マテリアルの Inspector の Albedo から、色を赤に変えておきます。
また、名前も分かり易いように Red に変えておきます。
マテリアルは、Project タブから Inspector 上のオブジェクトへドラッグアンドドロップをすると、適応できます。
上記手順を繰り返すか、複製をするかして、今度は黒の球体を作ります。
今度は BrackSphere と名付けました。
同様に、黒いマテリアルも作ります。名前を Brack と付けたうえで、BrackSphere に適応します。
赤と黒の球体がそろったところで、初期状態では暗くなった状態にしておきます。赤い球体を非表示にしておきましょう。
赤い球体を選択し、Inspector から、名前の横にある有効化のチェックを外します。
それから、これは必須ではないのですが、台座となる Base を Cylinder で作ったのと、それらを子供にしてひとまとめにしておくための Lamp を空のオブジェクトで作成してあります。
Socket の関数に設定
ランプのオブジェクトが用意できたら、次は Socket の関数に設定します。
対象の関数は、Socket の Inspector の XR Socket Interactor -> Interactor Event -> Select の中にある Select Entered と Select Exited です。
Entered が電池をはめた時、Exited が電池を外した時です。
はめた時は赤い球体を表示し、外したときは黒い球体を表示したいので、以下のように動くようにすれば、それらしく見えるはずです。
はめたとき
・黒い球体を非表示にする
・赤い球体を表示する
外した時
・黒い球体を表示する
・赤い球体を非表示にする
まず、はめたときの設定をしていきます。
Select Entered の + ボタンを2回押します。2つ出てきた設定項目に、それぞれ RedSphere と BrackSphere を設定します。
関数を指定するところ(No Function という表示になっているかと思います)に、GameObject -> SetActive (bool) を指定します。
チェックが付いていれば表示する、外れていれば非表示にするので、BrackSphere はチェックを外し、RedSphere はチェックを付けておきます。
同じように、外した時の設定もしていきます。
Select Exited に、BrackSphere の表示と、RedSphere の非表示の設定をします。
確認
では、満を持してテストしてみます。
バッテリをつかんでソケットに近づけると、はめられることを示す青い表示が出てきますので、バッテリから手を放します。
そうすると、バッテリがソケットにはまり、赤いランプが付きます。
バッテリー以外がはまらないようにする
ランプはつきましたか?それはおめでとうございます。
けど残念、これで終わりではないのです。
今のままだと、持てる物なら何でもソケットにはめられてしまいます。
同じバッテリーなら良いですが、銃や剣や回復アイテムをはめてもランプがつくのでは困ります。
いかづちの剣やいかづちの銃、いかづちの回復アイテムにしたくないのであれば、バッテリー以外をはめられないようにしておきましょう。
剣オブジェクト用意
はめられないようにするオブジェクトとして、今回は剣を用意してみます。
適当に Cylinder と Box で形を作り、持てるようにしておきます。
とてもかっこいい剣が作れましたね。デュランダルと命名しましょう。
え?仰々しい?では、オブジェクトの名前は Sword でいきます。
この Sword をソケットにはめてみると、ソケットを貫通しながらはまってしまうほか、ランプが赤くなっているのでバッテリーとして機能してしまっています。
何をはめても謎解きがクリアできるのなら、バッテリーを手に入れに行く必要がありません。
これでは困りますから、バッテリーしかはまらないようにしていきます。
Interaction Layer Mask の設定
理屈をすごくざっくり説明すると、オブジェクトに「バッテリー」属性を付け、その属性のオブジェクトじゃないとはまらないようにする感じです。
Battery オブジェクトの Inspector -> XR Grab Interactable -> Interaction Layer Mask を選択し、Add Layer をクリックします。
そうして出てきた Interaction Layers の User Layer 1 に「Battery」と入力しましょう。
そうすると、Interaction Layer Mask に Battery が表示されますから、それを選びます。
この時、チェックが入っているものすべての属性が付いてしまうので、一度 Nothing ですべてのチェックを外してから、あらためて Battery を選択すると確かだと思います。
同じように、Socket オブジェクトの XR Socket Interactor にも Interaction Layer Mask があるので、同様の方法で Battery だけにチェックが入った状態にしておきます。
この状態で実験してみます。
バッテリーはソケットにはめられますが、剣ははまらずに倒れていきます。
これで、一応はゲームに使える程度の知識にはなったんじゃないかと思います。
最後に
続きもそのうち上げていきたいです。次回は、VRゲームにおける銃の操作の考察を挟んで、「マガジンの残弾を取得する」の予定。
前回の投稿から、だいぶ長い期間が開いてしまいましたね。
私事として、就職して XR 部門の技術者になれたのはよいのですが、忙しくて記事を書けてませんでした。すみません。
note もそうですが、Youtube もぼちぼち復活させていきたいです。
それから、一応Vtuberやってますので、気が向いたらフォローしてやってください。
たまーにつぶやいて、ごく稀に配信してます。
Twitter:@Suzuran_Amano
Youtubeちゃんねる:スズランちゃんねる - YouTube
この記事が、あなたの開発の助けになることを祈っています。