FinalIK for VRChat [アイテム持ち替え] 

# はじめに
VRChat（以下VRC）での使用を想定したFinalIKの設定方法についてまとめました．

今回はFilanIKの基本的な使い方として，

- LimbIKを使ってアイテムをアバターの手に追従させる
- 二つのLimbIKを使ってアイテムの追従先を切り替える（手<->頭）

について説明したいと思います．

![OverviewCh01.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404071/87c4d872-7c38-70d3-5d7a-92fb4bb87db6.gif)


## 概要
FinalIKとはUnityのアセットで，IKを使ってアバターやオブジェクトの動きを制御できるツールです．
また，VRChat内に持ち込むことができる外部アセットの一つです．

<https://docs.vrchat.com/docs/supported-assets>


FinalIKを使うと多関節アームを柔軟に操作でき，例として動画のようなアバター改変をすることができます．
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr"><a href="https://twitter.com/hashtag/FinalIK?src=hash&amp;ref_src=twsrc%5Etfw">#FinalIK</a> for <a href="https://twitter.com/hashtag/VRChat?src=hash&amp;ref_src=twsrc%5Etfw">#VRChat</a> <br>現時点で理解できてることを全て詰め込んだスチームパンク・メカこんちゃんです<br>１フルトラ<br>２両足のフルトラを止めて空中浮遊<br>３サブアームの先端が足として動くモード．歩行アニメーションも追従します<br>４サブアームの床固定モード．体が上下移動しても柔軟に支えてくれます <a href="https://t.co/RzNv0lsmev">pic.twitter.com/RzNv0lsmev</a></p>&mdash; Chootana (@choo_zap) <a href="https://twitter.com/choo_zap/status/1364163383306592262?ref_src=twsrc%5Etfw">February 23, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


## 対象読者
VRCでFinalIKを使いたい方とします．
また今回はAvatar3.0でアバターをアップロードしたことある方を対象とします．
Avatar3.0については[VRChat　続･初心者向けUnity備忘録](https://booth.pm/ja/items/2612867)で一通りの設定方法を学ぶことをおすすめします.


## 環境
**注意**:
 VRCのバージョンによってVRC内でのFinalIKの挙動が変更される可能性があります．

動作確認した環境は以下の通りです．

- Unity: 2018.4.20f1 
- VRC: 2021.1.2
- [FinalIK](https://assetstore.unity.com/packages/tools/animatiON/final-ik-14290)
  - $90. セールで安くなるタイミングでの購入がおススメです！


# IK(Inverse Kinematics)について
アバター改変時に右腕の動きをチェックしたいとすると，Armatureの肩関節（Shoulder）を回転させて，次に肘関節（Elbow）を回転させて．．．とするかと思います．

このように各関節を一つずつ動かすことで全体の動きを作っていく仕組みを**FK**(Forward Kinematics)と呼びます．
肩関節から肘関節の順に回転させることで手の位置を求めるイメージです．

反対に，アバターの手の位置や姿勢が特定の位置・姿勢に合うように，他の関節の回転を計算する仕組みを**IK**(Inverse Kinematics)と呼びます．
手の位置が先に与えられて，肘関節から肩関節の逆順に必要な回転を求めるイメージです．

VRCでもHMDと2つのコントローラ（+トラッカー）の位置・姿勢からIKを解くことで体全体の動きを制御しているので，VRCをプレイする方には身近な存在だと言えます．


実際にIK制御するために必要なものは，以下の３つになります．

1. 複数の関節を持つモデル(実際に動かしたいキャラクターや多関節アームなど)

2. ターゲット(モデルの部位を合わせたい位置・姿勢)

3. IKコントローラー(VRIK, FBBIK, FABRIK, CCDIKなど)

FinalIKでは様々なIKソルバーがコンポーネントとして用意されています．


# 全体図
今回はIK制御を用いてオブジェクト（cube）を腕や頭に追従させたいと思います．
![overview.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404071/e42e82ac-94e0-e687-21fa-dbadaa7dfa3c.png)
全体の階層構造は以下の通りです．

- Avatar(VRC Avatar Descriptorがある階層)
    - Armature（HMDやコントローラで操作するスケルトン）
    - Body（スキニングされたモデル）
    - IKTargets
    - IKControllers
    - IKModel

用意したアバター直下に３つの空オブジェクトを追加して，それぞれ分かりやすいようにIKTargets/IKControllers/IKModelとします．
それぞれのオブジェクトについて実際に説明します．


### Point
VRCのバージョン変更によってFilanIKの挙動が変更されることがあります．
またVRCでのIKとFinalIKが衝突し，Unityでは上手く動作していてもVRCに持ち込むとおかしくなるケースを確認しています．
そこで，VRC Avatar Descriptorがある親オブジェクトとArmatureにFilanIK由来のコンポーネントを追加しないことで，VRCとの衝突を防ぎます．


# IKModel
IKで動かすためのモデルです．
![IKModel.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404071/5c0a6389-429d-2102-4e23-d098a58018f5.png)
IKModelの階層に，２つの関節に相当する空オブジェクト(Bone1, Bone2)と実際に動かしたいオブジェクト(Cube)を親子関係で追加します．
Bone1, Bone2を可視化してみると以下のようになります．
![Bone1Bone2Visualization_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404071/f54d55cf-5cc4-a36c-9b73-90095a120c56.png)
このようにBone1, Bone2，CubeのPositionをそれぞれ重ならないように，「く」の字に配置しておきます.
今回はBone2のxを1だけずらし，Cubeは好きな位置に設定しました．


# IKTargets 
次にターゲットとなるゲームオブジェクトを追加します．
![IKTargets.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404071/d3607f55-fb94-95f5-1369-8be838f10587.png)
IKTargetsの階層に２つの空オブジェクトを用意し，それぞれTarget2Hand, Target2Headとします．右手と頭の位置に対応させます．

ターゲットをアバターに追従させるためには，Armatureのある階層にターゲットを置く必要は必ずしもありません．
下図のようにParentConstraintを用意して，
1. Is Activeにチェックを入れる
2. Constraint Settingsで対応する関節を指定する（今回はhand.RとHead）
すると，アバター直下にあるターゲットが右手や頭に追従するようになります．
![IKTargetsInspector.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404071/2ca26a1a-cadc-c85e-5dd0-6a202b3182f5.png)


# IKControllers
今回の主役となるIKコンポーネントを追加します．
![IKControllers.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404071/3f829598-32cd-f515-3d0d-0cb8cd6d559d.png)
IKControllersの階層に２つの空オブジェクトを用意し，それぞれController2Hand, Controller2Headとします．

今回はLimb IKを使用します．
Limb IKとは腕や足などの，３つの関節を持つモデルを制御するためのソルバーです．
今回のIKModelは2つの関節＋cubeなのでこのコンポーネントが適しています．

下図のようにController2Hand/Controller2HeadにそれぞれLimbIKコンポネントを追加し，

1. Fix Transformsにチェック
2. Bone1, Bone2, Bone3にIKModelのBone1, Bone2, Cubeをそれぞれ追加
3. Targetに対応するTarget2Hand/Target2Headを追加
4. Position Weightを1に
5. AvatarIKGoalは今回はLeftFootに

と設定します．

Position Weightを１にするとIKModelのCubeをTargetの位置にぴったり合うように計算されます．
Rotation Weightを１にするとTargetの回転姿勢にも合うように計算されます．

![IKControllersInspector.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404071/a5f99eeb-6c09-8734-1296-83561158ceda.png)


これでCubeを追従させる準備がひとまず整ったので，動作確認してみます．
Controller2Handに追加したLimbIKコンポーネントにチェックを入れて，Controller2Headの方はチェックを外しておきます．

プロジェクトを実行後，アバターの肩関節を回転させて，
Cubeが右手に追従していれば成功です．（動画ではTargetを可視化させています．）
![finalik_item_hand.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404071/81754685-f06e-9aff-44b2-40d651fc5de9.gif)

# IKControllerの入れ替え
Cubeは基本的に右手に追従させて，切り替えで頭に追従させるとします．

今回はそのためにLimbIKを２つ用意しましたが，どちらのコンポーネントもONにしておくと両方についてのIkが解かれて，Cube位置が決定します．

この時Position Weightを1にしているので，必ずどちらかのTargetの方に移動しています．
このままVRCに持ち込むと，どちらのIKが解かれるかが未定なので，挙動が不安定になります．（特に多くのIKコンポーネントを連動させる時に注意）

そこでIKControllersにIK Execution Orderを追加し，

1. IK Componentsのsizeを1にし，
2. Element 0 にデフォルトとするController2Handを追加
3. IK Execution Order自体にチェックをいれる
4. Controller2Hand内のLimb IKのチェックを外しておく

と設定します．

IK Execution OrderはIKコンポーネントの実行順序を明示するもので，ここに追加されたIKはチェックが外れていても実行されます．

この状態でプロジェクトを実行してみると，デフォルトではController2Handが実行されており，Controller2HeadをON/OFFすることでCubeの位置を入れ替わります．
![finalik_item_hand2head.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/404071/fdab7931-32d6-547f-3fd2-19e71454b065.gif)
最後にController2HeadのLimbIKをON/OFFするアニメーションを作ればVRC内でも再現できます．
bool変数とON/OFFアニメーションで作れるので非常にシンプルです．

# 最後に
Unity上では上手く動作しても，VRCの仕様によって挙動がおかしいことがあります．
必ずアバターをアップロードしてVRC内で動作確認しましょう．