Final IKを使わないでアバターの関節を動かす方法

#はじめに
unity初心者です。ゼミ課題で「なんでもいいから夏休みの宿題としてなんかVRコンテンツ作ってきてね」という無茶ぶりを受けました。そこでせっかくだから3Dアバターを動かしてみようと思い立ち,アバターを動かすといえば**Final Ik!**と思ったんですが、90ドル(*1)もするFinal IKは一介の学生には中々手が出せない代物でした。
そこで何かないかと調べてみたらYoutubeで[いいもの](https://youtu.be/tBYl-aSxUe0)を見つけました。
何をやっているのかよくわからないけどとりあえず動画にそって進めていたら無事にアバターを動かすことができたのでシェアしたいと思います。筆者は未検証ですが、任意のアバターでもこのやり方が適用できるらしいです。ご自身のアバターでやる場合には自身のアバターとの差異に留意しながら読み進めて下さい。

1つの記事で全部書くと長くなりそうなので第3回に分けて投稿しようと思います。
今回はアバターの上半身の関節を動かします。

Unityのバージョンは**2019.4.6**で解説します。
2019.2以上ならとりあえずは大丈夫らしいです。

なおOculusIntegrationの導入は済んでいる前提で話を進めます。
導入の仕方はこちらの[記事](https://framesynthesis.jp/tech/unity/oculusquest/)と[動画](https://youtu.be/37I1ZATbGew?t=4796)に詳しいです。

## 1 上半身を動かす
まずは、アバターを置くPlaneを設置して、動かしたいアバターをunityに取り込みます。Rig>Animation TypeをHumanoidにしておきましょう。今回は動画の通り、Asset storeから[Robot Kyle](https://assetstore.unity.com/packages/3d/characters/robots/space-robot-kyle-4696)を持ってこようと思います。以下Robot Kyleのことをアバターと呼称します。

次にアニメーションリギングのパッケージを入れます。
Window>Package Manager>(右上にある)Advanced>show preview packagesにチェックを入れて右側からAnimation Riggingを押してインストールします。![Desktop Screenshot 2020.11.02 - 00.45.46.74.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517673/8d74e901-bd38-a8cd-b883-a834a36428c6.png)

次にアバターにコンポーネントを追加します。アバターを選択した状態で、Add Componentからrigと検索してRig Builderを追加します。これが追加されたことで自動的にAnimatorも生成され、Animationは必要なくなるためremove componentしてしまいましょう。
更にBone Rendererも追加します。
これから、色々なGameObjectをComponentにアタッチしていくため、Inspector windowをロックしておきましょう。Inspector windowの右上の南京錠のマークを押すことでロックをかけることができます。
そうしたら、Hierarchのアバターのボーンをすべて選択し、Bone RendereのTransformsにアタッチします。![OculusIntegrationTest - AvaterTutorial - Android - Unity 2019.4.6f1 Personal [PREVIEW PACKAGES IN USE] _DX11_ 2020_11_02 20_30_54-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517673/e3407b62-ef2b-bc68-d135-497217eec58b.png)

続いて、アバターの子オブジェクトとして空のGameObjectを追加します。ここではRobot Kyleの子オブジェクトのことです。作った空のオブジェクトの名前をVR Constrainsに変えておきましょう。
そしてそのままVR ConstrainsのAdd ComponentでRigを追加します。
更に、Robot Kyleを選択して、Rig BuilderのRig Layersに今さっき作ったVR Constrainsをアタッチします。

そうしたら、VR Constrainsの子オブジェクトに空のオブジェクトを追加して、Right Arm IKにリネームします。加えてそれにTwo Bone IK ConstraintというComponentを追加します。そのうえ、アバターの右腕の根本、真ん中、先端に当たるボーンをそれぞれRoot,Mid,Tipにアタッチします。今回は以下のようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517673/5c891555-81d0-c681-d702-20672329f79b.png)

Source objectがnoneになっているので、更に、Right Arm IKの子オブジェクトとして空のオブジェクトを2つ作り、それぞれ名前をTarget,HintとしてSource objectいかにそれぞれアタッチします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517673/c6ee91b4-5d40-7076-1728-dbfc83efa081.png)![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517673/1ad12a3a-d924-bb13-e91d-13ddcdf62ee8.png)

さてここからリギングに入ります。リギングは人間のやっていい所業じゃないですが、ここでは難しいことはしません。
Robot Kyleの場合、デフォルトだと手先と腕のボーンが連携していないために、手先だけ動かすと手先だけが移動して、腕から外れてしまいます。これを連携づけるためにさっき作ったTargetと、腕と直接つながっている手のボーン（ここではRight_Wrist_Joint_01）を複数選択したままAnimation Rigging>Align Transformを選択します。
全く同じことをHintでも行います。Hintと手先とつながった腕のボーンを両方選択して、Align Transformです。
ここで一度シーンを実行してみましょう。TargetやHintを選択して腕を動かしたり回転させたりして、脱臼したりせず適切に動けばOKです。

これで右腕のリギングは完了です。左腕にも同じことをしましょう。Right Arm IKをCtrl+Dで複製して、Left Arm IKにリネームします。
もちろん、Left Arm IKのTwo Bone IK Constrainrsには右腕のボーンが適用されているので左腕のボーンに置換します。3つ前の画像のRoot,Mid,Tipを全部Leftバージョンにに置換しましょう。これで両手分が完了しました！
試しに実行してみて両腕とも適切に動くことを確認しましょう。

今回のエントリでは上半身のみを扱うため、作業しやすいようここで一度、アバターの下半身を見えなくします。（筆者がアバターの下半身は筆者が続きを書く気力があったら次回復活します。）アバターの下半身はそのままがいいという方は消さないで次のステップに進んでいただいて結構です。
Root>Hipを選択して、scaleのxとyをともに0にします。これで下半身が見えなくなりました。

次に頭部のリギングを行います。
VR Constraintsの子オブジェクトとして、空のゲームオブジェクトを作り、Head Constraintという名前を付けます。そしてMulti Parent ConstraintというComponentをつけて、Constrainted ObjectにNeck>Headを、Source ObjectsにHead Constraintを,アタッチします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517673/bf062185-7160-5e92-eed8-5caffccf4e03.png)
ここまでやったら、先ほどまでと同じように、Head Constraintと、首とつながった頭部のbone(ここではNeck)を両方選択してAlign Transformします。

これで完成！と思いきや、首を動かしても体が追従して動かないのでもうひと手間加えてあげます。ここからスクリプトを書いていきます。

アバターにVRRigという名のスクリプトを生成して、以下のスクリプトをコピペしてください。

```
using System.Collections;
using System.Collections.Generic;
using UnityEngine;


[System.Serializable]

public class VRMap {

    public Transform vrTarget;
    public Transform rigTarget;
    public Vector3 trackingPositionOffset;
    public Vector3 trackingRotationOffset;


    public void Map()
    {
        rigTarget.position = vrTarget.TransformPoint(trackingPositionOffset);
        rigTarget.rotation = vrTarget.rotation * Quaternion.Euler(trackingRotationOffset);
    }


}

public class VRRig : MonoBehaviour
{

    public VRMap head;
    public VRMap leftHand;
    public VRMap rightHand;

    public Transform headConstraint;
    public Vector3 headBodyOffest;
    // Start is called before the first frame update
    void Start()
    {
        headBodyOffest = transform.position - headConstraint.position;
    }

    // Update is called once per frame
    void FixedUpdate()
    {
        transform.position = headConstraint.position + headBodyOffest;
        transform.forward = Vector3.Lerp(transform.forward,Vector3.ProjectOnPlane(headConstraint.up,Vector3.up).normalized,Time.deltaTime*5);//*turnSmoothness

        head.Map();
        leftHand.Map();
        rightHand.Map();
    }
}

```

動画からそのままコードを持ってきたので、コードの意味が全く分かってないけど動けばヨシ！ってことでコードの解説はしません。というかできません。（有識者助けて）

ここまでくればあと少しです。動画ではここでOVRCameraRigを入れてますが、どうせ後でアバターを歩かせたりするのでOVRPlayerControllerを導入します。ヒエラルキーにOVRPlayerControllerを入れてアバターを子オブジェクトに設定してください。その後、OVRPlayerControllerの子オブジェクトのOVRCameraRigのOVR ManagerのTrackingのTracking Origin TypeをFloor Levelにしましょう。
更に、アバターのVR RigのVR TargetとTracking に以下の図のようにオブジェクトをアタッチして、Position OffsetとTracking Rotation Offsetの数字を変えます。アバターによって値はよしなに変更してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517673/0e7d2763-078c-a376-08fe-d3868c57532f.png)

実行してみると......
![ezgif-3-5b26dfc0bd10.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517673/2effbed8-3ea5-f62b-8328-8d7c3746cde0.gif)

アバターの手を動かすことができました！めでたい！えらい！すごい！


**補足**
(*1)11/12現在FinalIKがセール中みたいです。

元動画の工程をほぼ忠実に再現したつもりですが、どこかで間違えがあるかもしれないことご容赦ください。
この続きはゆるゆりと書いていきます。

第2回：下半身を動かす・・・まだ
第3回：歩けるようにする・・・まだ