UnityでMMDモデルにVRIK使ったら手首の角度が変になったので直したい
未だにUnity出来ないマンしています。
8月くらいにVRIKを試して、手首の角度がおかしかったのを放置しつづけ、アドホックなやり方ですが、修正出来たので、自分用メモとしてまとめます。
とりあえずVRIKで動かす
UnityでMMDモデルを使えるというのは、MMD4Mecanimを使えば簡単にできるということが分かってましたが、 どうやらVRコスプレする際もVRIKというFINALIKのアセットを使えば、結構簡単にできるらしいとのことで早速試した結果がこちら。
適当にやった割には意外と上手くいっているように見えるんですが、手首がおかしいです。
別におかしな方向に曲げてたのではなく、手のひらを頭側にして両手をただ上げた状態です。
「なんでこんなことになってるんだ?」と思いながらも、Unity上でモデルの手首の角度を最初から変えたとしても実行すると全く無意味だったので、 変えるならインポートする前のモデルの情報をいじらないといけないのかなーとか、 トラッキングの手首の角度をとるところを変えるのかなーとか、 ぼんやり悩みながら、気が付いたら2か月くらい放置してました。
このときに参考にしたVRIKやFINALIK、MMD4Mecanimの記事がどれだったか完全に忘れてしまいました…。
MMD4Mecanimで取り込むときは、Humanoidでしましょうとか、モデルは十字になってないと上手くいきませんとか、そういったことが書かれていた記事があった気がするんですが、思い出せない。
うろ覚えですが、他では以下の記事を参考にしたような気がします。
ちなみにOVRPlayerControllerは使っておらず、OVRCameraRigを使ってます。
手首がおかしいところを直す
インスペクターでいじれるパラメータではどうしようもなかった(少なくとも見つけられなかった)ので、
VRIKのスクリプト -> OVRCameraRigのスクリプト
の順番でスクリプトを見ていきました。
VRIKはどうやら位置トラッキングはしておらず、動かすIKのモデルのReferenceを定義したりするだけっぽかったので、 Solverで指定しているのがOVRCameraRigのAnchorだったこともあり、OVRCameraRigに手のトラッキングのスクリプトがあるのだろうと思い、 該当箇所を探して、適当にオフセット値をぶっこむことにしました。
[OVRCameraRig.cs] // 省略 // // public変数の諸々が終わったあたりにつぎ足す // Startのところで初期化 // 値はモデルによって変わると思います public float lhandoffset_x; public float lhandoffset_y; public float lhandoffset_z; public float rhandoffset_x; public float rhandoffset_y; public float rhandoffset_z; // 省略 // private void Start() { UpdateAnchors(); lhandoffset_x = -90f; lhandoffset_y = 90f; lhandoffset_z = -30f; rhandoffset_x = -90f; rhandoffset_y = -90f; rhandoffset_z = 30f; } // 省略 // private void UpdateAnchors() { // 省略 // trackerAnchor.localRotation = tracker.orientation; centerEyeAnchor.localRotation = VR.InputTracking.GetLocalRotation(VR.VRNode.CenterEye); leftEyeAnchor.localRotation = monoscopic ? centerEyeAnchor.localRotation : VR.InputTracking.GetLocalRotation(VR.VRNode.LeftEye); rightEyeAnchor.localRotation = monoscopic ? centerEyeAnchor.localRotation : VR.InputTracking.GetLocalRotation(VR.VRNode.RightEye); leftHandAnchor.localRotation = OVRInput.GetLocalControllerRotation(OVRInput.Controller.LTouch); rightHandAnchor.localRotation = OVRInput.GetLocalControllerRotation(OVRInput.Controller.RTouch); // 付け足したところ leftHandAnchor.localRotation = leftHandAnchor.localRotation * Quaternion.Euler(lhandoffset_x, lhandoffset_y, lhandoffset_z); rightHandAnchor.localRotation = rightHandAnchor.localRotation * Quaternion.Euler(rhandoffset_x, rhandoffset_y, rhandoffset_z); if (UpdatedAnchors != null) { UpdatedAnchors(this); } }
いかにも手のAnchorの回転取得してますってところがあったので、そのあとに無理やり修正したい角度を加算する感じ。
Quaternionという訳分かんないものがあるので、テラシュールブログのこの記事を参考に適当に足し込む。 後で本気でQuaternionを勉強しないといけない気がする…。
直った結果がこれ
いろいろまだ直さないといけないところを感じるけど、手首が変な角度で曲がるのは直った感じ。かわいい。
なんか手首ひねると、ツイストするみたいにちぎれそうになったり、腕とかが手首の位置優先で体突き抜けたり、いろいろ問題がありそう。