UE4でVRIKみたいなことしたい


[Unreal Engine 4 (UE4) その2 Advent Calendar 2017](https://qiita.com/advent-calendar/2017/ue4second)の4日目です

普段はUE4やUnityでVRコンテンツを作っているプログラマです。
今回は標準機能のブループリントだけ使ってIKを使う方法について記事を書きます。

#VRとIK
VRコンテンツでは自分や他人の動きを表現するのにIKを使ったアバターを使うことが多いです。
ヘッドマウントディスプレイ(HMD)と両手のモーションコントローラの位置情報をもとに、アバター全身の動きを表現します。
これによって、VRの没入感を向上させることができるのです。
[![IMAGE ALT TEXT HERE](http://img.youtube.com/vi/VfEJghTL-e0/0.jpg)](http://www.youtube.com/watch?v=VfEJghTL-e0)
[![IMAGE ALT TEXT HERE](http://img.youtube.com/vi/688XEeK80GQ/0.jpg)](http://www.youtube.com/watch?v=688XEeK80GQ?t=22s)

Unityの場合Final IKという有名で優秀な有償アセットがあり、これを使ってIKアバターを作ることが多いです。
なんとUE4の場合、標準で用意されているIKの機能だけでこれに近いことができるので、その方法を紹介します。


#準備
- UE4.18
- ThirdPersonSampleの中にあるMannequinアセット(グレイマン)

なお、今回の記事は英語版エディターの表記を使っています

#手を動かしてみよう
##AnimInstanceの作成
Content Browserで右クリックし、Animation->Animation BlueprintでAnimInstanceを作成します
Parent Classには「AnimInstance」SkeletonにはMannequinのSkeletonを選択します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/105021/4d877f1f-eafc-c998-39b1-ea6d0c78ee13.png)

作ったアセットをダブルクリックしてAnimGraphを開きます。
右クリックしてFABRIKノードを作成します
![image.png](https://qiita-image-store.s3.amazonaws.com/0/105021/82b3bc90-ca43-d5ea-365d-1dcfd6e80564.png)

##FABRIKノードの設定
Effector Transform SpaceをWorld Space
Effector Rotation SourceをCopy Target Rotation

Tip Boneをhand_l
Root Boneをupperarm_l
に設定します
![image.png](https://qiita-image-store.s3.amazonaws.com/0/105021/9b136b76-acc2-25f1-f0b3-4fc38afa96ac.png)
右手側は「_l」の部分を「_r」に置き換えてください。


##変数の作成
右手、左手、頭のTransform用の変数を作成しておく。
このとき、あとでBlueprintからアクセスするので全部Publicにしておきます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/105021/2ec5c331-4dab-2559-a7e0-2dd62531570e.png)


##ノードをつなぐ
Local to ComponentとComponent to LocalでFABRIKノードを挟んで、Final Animation Poseへ流し込んでやります。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/105021/14d3053e-387e-2e7d-68b4-fcb1e0d4e6bd.png)
コンパイルすると
![image.png](https://qiita-image-store.s3.amazonaws.com/0/105021/f6218801-cfc1-9d28-9d2e-71815183640d.png)
手が変な方向に、、、。
手の座標が原点になっているためプレビューでは手が変な方向に行きますが、IKが効いている証拠です。

あとで調整しやすいようにオフセット用ノードを挟んでおきます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/105021/09356059-8fcb-4716-e420-2ca2f7d78a12.png)

左右の手を実装するとこんな感じ
![image.png](https://qiita-image-store.s3.amazonaws.com/0/105021/1792e88b-fe1c-8c89-8bac-aa6317aa6b9a.png)

##AnimInstanceにBlueprintから値を流し込む
今回作ったAnimInstanceを使ったPawnを作って動作確認しました。
Pawnのブループリントの構成は下記の図の通りです。
CameraとMotionControllerComponent2つ。
そして、SkeletalMeshComponentを設定します。
この時SketetalMeshComponentはX軸が前方向になるように回転させています。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/105021/a3776cf8-e9e2-8b09-b17f-5d666dad3636.png)

Event Graphは下記の図のようにしました。
毎フレームMotionControllerのTransformをAnimInstanceに流し込んでいます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/105021/3d245eb0-61ad-c717-5c39-21688265833c.png)

こうするとコントローラにバターの腕が自然と追従してくれるようになります。
手をぐるぐる(手首の角度は要調整・・・)
![arm.gif](https://qiita-image-store.s3.amazonaws.com/0/105021/f97a1a42-0f87-b756-ddcb-db2665c545e5.gif)


#膝を曲げてみよう
手の追従ができたら次は頭なのですが、頭をただ追従させるだけだと
実際の人間がしゃがんだ際にアバターの首が体にめり込んでしまいます。
それを防ぐために、ある程度頭が低くなったら、アバターの膝を曲げて頭の位置を下げてあげます。

##LegIK
UE4にはLeg IKという足用のIKノードが用意されています。
さらに、Graymanには「ik_foot_root」という足用のIKボーンが組み込まれています。

Leg IKのノードを作成し、Legs Definitionを1つ追加します。
そして
IKFoot Boneにik_foot_l
FKFoot Boneにfoo_r
を設定します。右足も同じように作成します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/105021/11c2d6de-9a68-0503-03d4-f852e932dde9.png)

##ik_foot_rootの操作
ik_foot_rootの座標を操作することで膝が曲がるようになります。
ik_foot_rootのボーンを直接操作するために「Transform (Modify Bone)」ノードを使用します。
このノードを使用するとボーンのTransformを直接指定することができるようになります。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/105021/0843c2d2-ae7c-b017-a9dc-805a63f09da9.png)
今回は
Bone to Modifyをik_foot_root
Translation ModeをReplace Existing
Translation Spaceを**Parent Bone Space**
に設定しました。
そして、FootZというFloatの変数を作成し、この値を変化させることで、ik_foot_rootの高さを変化させます。
FootZの値を適当に変化させると下記の図のように膝が曲がるようになります。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/105021/13e41758-2f21-5c37-236d-9da037866b3e.png)

##Rootの操作
しかし、このままでは膝が曲がるだけで宙に浮いてしまいます。
そこで、Rootの値を変化させ膝を曲げつつも、足は接地させるように修正します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/105021/57674d63-c4be-100f-49d3-23878f6a0aad.png)
まずRootTransformという変数を作ります
そして、Transform (Modify Bone)ノードを再び作成し
Bone to Modifyにroot
Translation ModeをReplace Existing
Translation Spaceを**World Space**
Rotation ModeをReplace Existing
に設定します。
そして、膝を曲げた分だけRootの位置が低くなってくれればいいのです。
新しく作成したFootZとRootTransformの変数が更新されるようにEvent Graphに処理を書いていきます

##Event Graphの作成
![image.png](https://qiita-image-store.s3.amazonaws.com/0/105021/591ff7c6-afd8-5abe-9e6b-bd590e06f131.png)
Event Graphのタブに切り替え、変数の処理を書いていきます。
Event Graphでは「Event Blueprint Update Animation」が毎フレーム呼ばれます
今回は「頭の位置から逆算して足の高さを決定する＋膝の曲げる量を調整する。」という2つの処理を行っています。
頭の位置が入ってくる「Head Target Location Z」からアバターのおおよその身長である180を引き
-80～0に丸め込みます。この値がRootの高さになります。
そして、正負を逆転させた値を膝を曲げる値であるFootZに渡します。


完成したAnimInstanceのAnim Graphは下記のようになります。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/105021/8c26a6cc-dae1-9c94-ecfb-4c2cb6cdfbdc.png)


最後にHMDのTransformをHead Targetに流してあげます。

完成したPawnはこんな感じになります。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/105021/d7583828-bd0b-3be2-6c22-3100c9bc6eab.png)


#完成
以上のことを実装すると下記のような動きができます。
これだけでも何となく人間らしい動きになっています。
この状態で頭と両手の位置情報を通信で同期すればアバターコミュニケーションが実現できます。
![hiza.gif](https://qiita-image-store.s3.amazonaws.com/0/105021/9a6b7798-54a6-3567-1ce2-6fcb44083233.gif)
![hiza.gif](https://qiita-image-store.s3.amazonaws.com/0/105021/178a2ab5-b17a-576f-57cf-e766368f9bae.gif)

未実装な項目として
- 手の角度
- 指の動き
- HMDの角度をいい塩梅で頭の角度に変換する方法
- 足と地面の自動接地機能
この辺も出来るとさらに完成度の高いアバターになっていきます。

また、オリジナルモデルを使いたい場合は、ik_foot_root部分のボーン構造をまねて作れば今回の方法で行けるはずです。

##プロジェクトファイル
今回のプロジェクトファイルは
https://github.com/tkada/ue4_vrik
に置いてあります。ご自由にお使いください。

明日は[unaunagi](https://qiita.com/unaunagi)さんの「ポストプロセスマテリアル製ディフュージョンフィルタ」です。

#参考資料
- [UE4 IKを使ってリアルタイムにボーンを制御してみる - Let&#39;s Enjoy Unreal Engine](http://unrealengine.hatenablog.com/entry/2017/06/26/221437)
- [UE4でVR用のIKを実装してみる話](https://qiita.com/HImaJin_Tw/items/2883aace0e10bb77065a)
- [IK 設定 - Unreal Engine 4 Documentation](https://docs.unrealengine.com/latest/JPN/Engine/Animation/IKSetups/index.html)
- [UE4で鏡を作る。](http://unrealengineue4.blogspot.jp/2015/07/ue4.html)