マトリックスと言えば、
ネオが弾丸を手で止めて落とし、緑色のマトリックスの世界に変わる
このシーン。
昨年、久々にマトリックスの新作映画レザレクションズを鑑賞し、このシーンを作りたくなったので制作してみました。
アプリケーションが起動すると、終盤のアパートの廊下でエージェントが正面に3体いるシーンが出てきます。
エージェントたちが銃を撃ってきますが、手を前にかざすと迫る弾丸を止められます。弾丸が静止したら、親指と人差し指をつまむように近づけると、弾丸を動かせるようになります。
指を弾丸から離すと、弾丸が地面に落ちた後に、周囲が緑色の文字が縦に流れるような見た目に変わります(ちなみに、この演出は「マトリックスコード」というそうです)。
基本的にはUnityをインストールして、上記のアセットや機能を導入していきました
今回は後述のシェーダー作成でShaderGraphを使うため、URP(ユニバーサルレンダリングパイプライン)を有効にしました。プロジェクト作成時にURPが含まれたパッケージを選ぶと楽です(後から導入も可能です)。 【Unity】URP(Universal Render Pipeline)の概要&導入方法
マトリックスコードを再現するため、以下のURLを参考にシェーダー(ShaderGraph)を組みました。 URPでマトリックスコードシェーダー
なお、シェーダーの元になる素材(文字をまとめたテクスチャ画像)は参照先からお借りしました。
基本的にはUnity用のOculus SDK(Oculus Integration)を利用します。SDK内のプレハブを置くだけでVRに最低限必要な機能は実装できます。
Quest2のVR描画やヘッドトラッキングは OVRCameraRig が担っているので、これをプレイヤーの立ち位置においてください。また、ハンドトラッキングと手のモデル表示のため OVRHandPrefab を使いました。ただ、(制作当時は)ものを掴む機能がなかったので、その処理は自作のスクリプトで実装しました(後述)。
なお、ワールド構築は適当にCGを用意してもらえばOK(地面には当たり判定をつけておきましょう)。 ここでは以下のアセットを使いました。
また、弾丸が地面の当たり判定にぶつかった後、2秒後くらいにワールドのシェーダーを作成したものに変えて、マトリックスコードを表示するようにしています。
手の位置や指の曲がり具合は、SDKで用意されているスクリプト(OVRHand, OVRSkeleton)から読み取ります。また、手のプレハブには当たり判定(物理接触なし)がデフォルトでついてます。
一番肝心なつかむ処理については、弾丸に当たり判定と独自のインタフェースを付けたうえで、接触したら指が弾丸をつかむか判定するスクリプトを組みました。つかむ判定は、指が触れていて、かつOVRHandのGetFingerPinchStrengthというメソッドが指を閾値以上に曲げているかを見て処理しています。また、起動時に指定の指(右手の人差し指)へ弾丸に接触した時のイベントを割り当て、つかんだ時に弾丸やワールドの設定を変えています。
(今ならInteraction SDKでより簡単に実装できそうですが...)
弾丸は物理演算(RigidbodyのAddForce、かつForceModeをImpulseに設定)で発射します。
先述の通り、当たり判定をつけていますが、物理判定のみでは弾丸が指に触れたとき余計な動きをしてしまうので、物理的な当たり判定の外にトリガー式の当たり判定をつけて、指が弾丸をつかんでいる間は物理演算が働かないように処理しています。また、指を離すと弾丸が地面に落ちるよう、物理演算を復活させています。
(指定のアセットが配信停止なので、参考程度に)
Chronosで(自分以外の)時間を1/10にしつつ、手をかざした時に減速して停止するよう、周囲に当たり判定をつけ、その中に入った弾丸の空気抵抗(Drag, AngularDrag)を大きくしています。