以前,OVRGrabbableについてご紹介しました. この時, SnapPoint
は非常に使いにくいので使わないように設計しましょうという話をしました.
SnapPoint
を使わない場合, オブジェクトの座標(原点)は下の画像のように設定します.
これが銃なら大した違和感はないのですが(z軸を銃口の向きと一致させるため), 剣や刀の場合はこのようにオブジェクトの見た目の向きとは異なる方向をオブジェクト座標系は向いています.これでは剣を並べたり, 剣を飛ばしたりする時の設計が非常に面倒なことになってしまいます.
そこで今回は直感的に使えるSnapPointを実装していきます.
では実際にどうすればいいのかということですが, 要はオブジェクトを掴んだ時と掴んでいない時でメッシュとコライダーの位置を変えてしまえばいいのです.
次の3つのスクリプトをダウンロードしてUnityのプロジェクトに追加してください. これらのスクリプトはそれぞれ次の機能を持っています.
CustomOVRGrabbable.cs
: OculusのOVRGrabbable
に使いやすいSnapOffsetを実装したもの. さらにCustomOVRGrabber
から掴んでいる手(右手か左手か)を取得してコントローラの状況を取得できるようにしている.CustomOVRGrabber.cs
: OculusのOVRGrabber
にコントローラの情報をCustomOVRGrabbable
に送れるようにしたもの.IfGrabbable.cs
:CustomOVRGrabbable.cs
用のインターフェース
Grabbable
側からコントローラの情報を取得する方法については, Kohki Nakajiさんの記事を参考にさせていただきました.

これらのスクリプトの使い方は次の通りです.
OVRGrabber
をCustomOVRGrabber
に置き換えます,CustomOVRGrabbable
のパラメータはOVRGrabber
と同じにします.OVRGrabbable
をCustomOVRGrabbable
に置き換えます,CustomOVRGrabbable
をアタッチしたオブジェクトを次のような構成にします.
BodyTrans
に持ちたいオブジェクトを設定します. 今回は剣です.GrabTrans
に持った時にGrabberのGrab Transform
にスナップさせるTransform
を設定します. 内部的にはGrabTrans
とGrab Transform
が一致するように持った時にGrabTrans
とBodyTrans
を移動させています.
別の刀剣になりますが, 実際に使用したのが次の動画です.
左の刀がOVRGrabbable
で右の剣がCustomOVRGrabbable
を使用したものです. 大きい矢印がそれぞれの原点と座標系を表しています. 剣についている小さい矢印がGrabTrans
です. 掴んでいる時にGrabTrans
(とBodyTrans
)が移動していることがわかります.
2020/1/24追加
CustomOVRGrabbale.cs
を更新しました.
– Start()
を削除.
– GrabBegin()
とGrabEnd()
内のオブジェクトの移動をそれぞれSetGrabbedArrangement()
, SetUngrabbedArrangement()
というメソッドに移行.
– GrabBegin()
とGrabEnd()
にコールバックを追加することができるようになる.
– プロパティにcontroller
を追加. 別のスクリプトからでもコントローラの状態にアクセルすることが可能に.
– メソッドMoveInHand()
を追加.Grabberのgrabpointの位置と姿勢を渡すことで,オブジェクトを手元に移動させることができる.
OVRGrabber.cs
との間に起こるバグを確認しました.
CustomOVRGrabbaleを持ったオブジェクトが持っている間に破壊された後,掴んでいた手でものが掴めなくなることがあります(おこらないこともあるが詳細不明).OVRGrabber.cs
のBeginGrab()
でgrabbableCollider
がnull
になっておりnullの例外エラーが発生しています.対処療法ですが,grabbableCollider
のnullチェックを行ってください.具体的にはfor (int j = 0; j < grabbable.grabPoints.Length; ++j)
の{}
の中でCollider grabbableCollider = grabbable.grabPoints[j];
の次の行以降をif (grabbableCollider != null){}
で囲ってください.
コメント