Unity上のHumanoidアバターで姿勢を判定(採点)しようとして苦労した話
まえがき
大学の研究でPerceptionNeuron2.0とUnityを使用して、とあるアプリケーションを開発しているのですが、開発していて苦労した(している)、Unity上のHumanoidアバターで姿勢の判定を行う手法の話をしたいと思います。
それとはあまり関係ありませんが最近Viveとトラッカーを購入し、フルトラVRChatにドハマりしていて、VR世界に自分の体を入れられる!!モーキャプってすげー!!ってなっています。
やったぜ pic.twitter.com/PkxzzvjiDn
— Agry@VRC (@___Agry___) 2018年10月27日
やろうとしたこと
PerceptionNeuronでUnity上のHumanoidアバターを動かし、姿勢を判定(採点)しようとした。
例えば、下の図のような女の子座りをお手本の姿勢とします。PerceptionNeuronを使って自分の体でHumanoidアバターを操作して、下の図と同じ女の子座りの姿勢をとることができているか、アバウトに判定(関節の曲がり具合などが同程度か判定)がしたいという感じです。
試してみて上手くできなかった手法
いくつかの手法を試しました。
3DCGの世界では姿勢の計算などにクオータニオンという四元数が良く使われるらしいので、模範姿勢の各関節のクオータニオンを計算してそれに近い値を取れていたらOKとしてみたり。UnityのInspectorから弄れる値localEulerAngleなどのオイラー角を使ってみたり(ジンバルロックさん...!?)。
とにかく閾値の設定が面倒だし、プログラムは汚く複雑になるし、デバッグとか細かい調整とか絶対やりたくない。
(ここに書かれているのは僕が技量不足のために実現できていないだけかもしれません。)
Unity初心者の独断と偏見での結論
ここに書く結論はUnity初心者の考えであり、もっと良い方法があるかもしれませんし、もしあるのであれば教えてほしいです。切実に。
アバウトに姿勢を判定したいのであれば、アバターのHipなどの子オブジェクトとして、Colliderを設置してあげて、そのColliderに指定した関節が入っているか(下の図のような感じ)で判定するのが良いのではないかという結論に至りました。
例えば、HeadCheckというオブジェクトは模範姿勢を真似する上で、アバターのHeadがあるべき位置に設置されています。ほかのColliderObjectも同様に設置されています。
従って、上の図のようにColliderObjectの位置に指定された関節部位を入れることで、模範姿勢と同じ姿勢をとることができます。
末端の関節(手先や足先、頭など)まで完璧に同じ姿勢が取れているか判定することはできないかもしれませんが、アバウトに判定したいのであればこの方法が使えるかと思います。
もし判定を厳しくしたり、末端の関節の判定まで完璧に行いたいのであれば、ColliderObjectをさらに小分けにして、細かく判定してあげれば良いのではないかと思います。逆にColliderを大きくすれば判定を甘くすることもできますね。
ちなみにColliderに指定された部位が入っているかどうかの判定を行うのはC#であればOnCollisionStay()を使えばできます。(RigitBodyとIsTrrigerを忘れずに)
marunouchi-tech.i-studio.co.jp
まとめ
姿勢判定を行うことができれば、「あるポーズをとったら変身!」とか、「両手を腰の右隣に持ってきたらかめ◯め波をチャージ!」とか、色々なことができます。
今回はColliderはHumanoidアバターの姿勢を判定するのにも使うことができるという話でした。時間があれば何か面白いゲームでも作ってみたいです。
あとがき
今回いろいろやってみて分かったことはこれです。
Unityってとても便利なんだからその便利な機能を使わないでプログラムでゴリ押ししようとすると苦労するってことを学んだ
— Agry@VRC (@___Agry___) 2018年11月17日
スクリプトで姿勢を判定するよりも、当たり判定を使って実現した方が目で見てわかりやすいですし、細かい調整もかなり楽です。
なかなかいい方法が思いつかなくて苦労しましたが、その過程でクオータニオンのことや、Unityの細かい機能のことなど、様々なことを勉強できたので良しとします。
© Unity Technologies Japan/UCL