UnityのSAFullBodyIKでフルボディトラッキング

#概要
HTC ViveとUnityを用いた、[Final IK](https://assetstore.unity.com/packages/tools/animation/final-ik-14290)を使わないフルボディトラッキングシステムを作ってみました。

Unityでのフルボディトラッキングは現在Final IKというアセットに付属しているVRIKを用いるのが主流です。が、有料アセットです。
なので、どうにか無料アセットだけでそれっぽいものを作れないかと奮闘しました。

#この記事を読んでできること
Unityにデフォルトで実装されている両手両足と視線のIKに加えて、SAFullBodyIKを使うことで腰と両肘、両膝をトラッキングできるようになります。

#開発環境
・HTC Vive Pro eye
・HTC Vive Tracker ×3 
・SAFullBodyIK

SAFullBodyIKはHumanoidにフルボディでIKを適用してくれるコンポーネントです。

SAFullBodyIKは下記サイト様にて公開されております。
[Stereoarts Homepage](http://stereoarts.jp/)
#事前準備
SteamVRセットアップが必要です。
今回使用するのはVRの位置同期のみなので、ボタン入力取得等の知識はなくても問題ありません。

#手順

##①モデルの用意

今回の説明ではモデルとして[ユニティちゃん](https://assetstore.unity.com/packages/3d/characters/unity-chan-model-18705)を使用しますが、Humanoidの適用されているモデルであればどれでもOKです。

まず、ユニティちゃんのprefabを配置します。付属のスクリプトは使わないのですべて消します。
Animatorも使用しないので、非アクティブにしておきましょう。
![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/519691/247e33ec-4071-5310-9686-06174b06a6c9.png)

##②Humanoidの設定

もし外部からインポートしたモデルを使用するなら、Humanoidを使うためにAvatar設定をする必要があるかもしれません。
具体的にはモデルの「ImportSetting > Rig > AnimationType」がHumanoidになっていればOKです。
Humanoidについては今回は割愛します。詳しく知りたい方は「Unity Humanoid」などで調べてみてください。


##③SAFullBodyIKのアタッチと設定

前述のサイトからSAFullBodyIKをダウンロードし、展開したフォルダをそのままProjectビューのAssets直下にドラッグ＆ドロップでコピーします。これでUnityへのインポートは完了です。
インポートしたフォルダ内の[Scripts]フォルダを開きましょう。

先ほど用意したモデルに、FullBodyIKBehaviour.csをアタッチします。
すると、モデルの下にFullBodyIKというオブジェクトが追加されます。![キャプチャ2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/519691/01bb2af8-5201-e097-e4d3-ef36c6fea0ea.png)

この状態で実行し、FullBodyIK以下のオブジェクトの位置や回転をいじってみると、対応した箇所が動きます。![キャプチャ3.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/519691/0135ea59-e3d6-c805-a4b5-01e2a2f1d0e5.png)


##④SAFullBodyIKの設定


コンポーネントのEffectorタブから、各関節のIK影響度の調節が行えます。
![キャプチャ4.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/519691/c70b2d22-d8ec-0dec-8ef5-4f54207174b5.png)

  SAFullBodyIKの各パラメータについての説明

- チェックボックス
そのボーンの操作が有効であるか。
ここが外れていれば、そのボーンのほかのパラメータをどれだけいじっても意味がありません。
逆に言えば、コントローラーで操作しない関節のチェックは外しておくべきです。そうしないと誤作動が起こる可能性があります。


- 各パラメータ。パラメータ名の右のスライダで調節。無効←　→有効。
    - pos:そのボーンに対しての位置移動がどの程度有効であるか。
    - pull:そのボーンの移動・回転が、ほかの可動ボーンに対してどの程度影響を与えるか。
   - rot:そのボーンに対しての回転移動がどの程度有効であるか。

pullに関しては言葉はわかりにくいので、具体例を。
例1：rightWristの位置とpullステータスの関係

- pull:なし
![キャプチャ6.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/519691/d654f8fe-11df-4f98-104e-f5270e406cca.png)

- pull:あり
![キャプチャ5.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/519691/e96321d3-9f22-00d9-092d-0c3714021f95.png)

pullありの場合は、rightWrist（左上の緑ボール）に全身が引っ張られているのがわかります。



さて、設定していきます。

まず、FullBodyIK内の階層を以下のように変更します。
![キャプチャ7.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/519691/7359fd98-b63a-220b-aa0f-a69f99153cff.png)

次に、VRで操作しやすいようにEffectorのパラメータを設定します。

1. Headのpos,rotを有効にし、三つのスライダをすべて最大（右端）にする。
2. Head以外の操作したいボーンのpos（チェック可能ならrotも）を有効にし、スライダは**pullを最小に**、**posとrotは最大に**する。
3. それ以外の使わないパラメータはすべて無効にする。


例えば、両足と腰をトラッキングするなら、設定は以下のようになります。（画面外のパラメータのチェックは外す）
![キャプチャ7.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/519691/562e6b27-feba-244b-ccc7-e19838543e6e.png)




##⑤コントローラーの操作適用

```c#:TransformSync.cs
using UnityEngine;

public class TransformSync : MonoBehaviour
{
    public Transform target;

    void Update()
    {
        transform.position = target.position;
        transform.rotation = target.rotation;
    }
}
```

適当に位置同期させるスクリプトを作ります。Hips、FootなどのFullBodyIKの動かしたい関節のオブジェクト（rightwristなど）にアタッチし、targetにその部位を移動させるコントローラーを設定します。

もう一つの方法としては、EffectorタブのShow Transformにチェックを入れると移動対象のTransformを設定できるので、こちらで直接コントローラーを参照するのもアリです。
![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/519691/5c9640e4-a4f6-5e52-d2b5-10e98183440b.png)

両方に共通することですが、コントローラーの参照は、コントローラーの子として空オブジェクトを作り、そのオブジェクトを参照するようにしましょう。
なぜかというと、FullBodyIKの可動位置とVRで使いたい可動位置にはズレがあるからです。

- VRで使いたいHeadの位置
![キャプチャ4.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/519691/7710f29e-78ea-ce66-7658-fa66fee65c49.png)

- FullBodyIKのHeadの位置
![キャプチャ3.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/519691/048af71a-ed2f-7add-f89e-5d1fd32241a8.png)

ということで、このギャップを埋める必要があります。
・設定例
![キャプチャ2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/519691/1cc4e46b-faca-45ea-bfd0-929bdf0bddb6.png)

このようにして、空オブジェクト（図ではHeadControl）をコントローラーとして参照し、座標を動かすことで、理想とするコントローラーの設定に近づけやすくなります。

例：HeadControlを参照して、視点のカメラをHeadとして設定する場合

- HeadControlのpotitionが(0,0,0)
![キャプチャ6.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/519691/3659e8c2-44cd-f86a-ff4c-b31df04bc2ae.png)
カメラが口の中に埋まってしまっています。

- HeadControlのpotitionが(0,-0.06,-0.1)
![キャプチャ5.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/519691/49a671a5-9ef7-6d80-ffed-1091f736d2fd.png)

空オブジェクトの位置を適切に調整すると、カメラと目線の位置を合わせることができます。
手、腰、足なども、モデルや利用者の実際の体形などに合わせて調整しましょう。


#完成！

HMD、コントローラー、トラッカーを各部位に設定すれば、後ろを向いたり、腰をひねってポーズをとったりと、自由に動き回ることができます。
腰をひねってkawaiiポーズをとろう！

#まとめ
手や頭の可動回転域が狭い、個人の体形差やモデルの差を吸収できないなどいくつか問題点もあります。（スクリプトである程度改善できますが）
ただ、工夫次第でフルボディトラッキングを生かしたゲーム開発にも利用できるかと思います。



##時間があれば次に書きたいこと
アイトラッキングを用いた視線移動
リップシンク

#ライセンス
© Unity Technologies Japan/UCL