【UE4】UE4ぷちコン15で使ったControl Rigまとめ

[1]:https://historia.co.jp/ue4petitcon15
[2]:https://youtu.be/FIa-Qs-_cto

[株式会社ヒストリアさん主催の第15回UE4ぷちコン][1]のまとめ。

# 色々残念ながら…

審査結果発表会からすでに10日以上たっていて、今さら感が強いが、今回応募した作品はこちら：
[両手両足をかわるがわる動かすゲーム - Youtube][2]

以下は一部を抜粋したGIF動画
![20210426_02_ControlRig.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358170/bcc61a1c-e0fa-4055-9661-7cb19a9dab19.gif)

（終始こうやって壁を登っているだけ…）

- 残念１： 時間が足らず、ゲームにならなかった。技術デモということでご容赦ください。
- 残念２： もちろん、賞をいただけるわけもなく。

とはいえ、興味深い作品の紹介枠(?)で紹介していただけた。ありがたや。

# ボルダリング(崖登り)のしくみ

今回は「プロシージャルアニメーション」がメイン。
プロシージャルアニメーションとは「アニメーションをただ再生するだけではなく、プログラムで加工して状況に応じたポーズを作っていく」といったところだろうか。

このボルダリングの動きは以下のような仕組みで作った。

## アニメーションは２つ

ポーズ編集用のコントロールリグ＋シーケンサーで、ボルダリング時の手足の伸び切った状態、縮み切った状態の２つを作成した。
どちらも１フレームしかない固定のポーズ。

|伸び切った状態|縮み切った状態|
|:------------:|:------------:|
|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358170/47385246-b5bd-d24d-7aa2-50d48e730080.png)<br />Aポーズ|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358170/ab5dc382-2584-5c91-5add-c9de6770b9b7.png)<br />Bポーズ|

これらを、Anim Blueprint 内で、右足／左足の IK の伸び具合を Alpha にしてブレンドしている。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358170/9fe93ef6-19dd-ff27-105c-2e6d58eba429.png)

> `IKAlphaLength_L, _R`は、足が伸び切ったときの`thigh`から`foot`までの長さに対する、現在の`thigh`から`foot`までの長さ（…の比率）

大雑把には：

- 両足が伸び伸びるほど、Aポーズに近づく。
- 両足が縮めば縮むほど、Bポーズに近づく。
- 片足が伸びて、もう一方が縮んでいれば、AとBの中間くらい。

…みたいな感じになる。

## これを Control Rig で加工する

Aポーズ／Bポーズのブレンド結果をコントロールリグに渡して加工する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358170/72c20aad-53af-daba-ae4c-5173c3dd50f3.png)

大量にパラメータがあるが：

- 最初の３つ：`PelvisAdditive`, `SpineAdditive`, `HeadAdditive`
    - 手足の伸び具合から、なんとなく体幹(spine等)をねじる角度を指定。
    - 込み入った計算はしておらず、手足のIKの長さに対して、20度ねじる、とかそういうシンプルな式。
- 続く４つのTransform：`IKToeL`, `IKToeR`, `IKHandL`, `IKHandR`
    - Pawn からもらってくる、両手両足のTransform。
    - これはユーザーがゲームパッドで操作する。
- その他のパラメータは割愛（ごめんなさい）

### Control Rig のノードグラフ

非常にでかい上に、皆さんの参考になるかどうかすらわからない…
![ControlRig_Boulder-Rig Graph.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358170/e2673057-2f6d-fc06-448e-996defe58b7d.jpeg)

Anim Graph の `Control Rig` ノードのソースピンに渡されたポーズのTransformが各ボーンにセットされた状態でControl Rigに来る。
Control Rig内では：

- もらった角度だけ、体幹(`pelvis`, `spline_01`, `spine_02`, `spine_03`, `neck_01`, `head`)を愚直にねじる。
- 両手両足は、`Basic IK`。つまり２ボーンIK。
- 妙にでかいのは、スケルトンの大半に渡るボーンの計算が２回行われているから。
    - 前半部「if runtime, make rigs' transforms from bones」と書いた箇所で、Anim Graphの引数からもらった値をボーンに適用
    - 後半部「rigs to bones」と書いた箇所で、リグのTransformから各ボーンのTransformを算出
    - これはもう仕方がない。（せめて関数に分けたい！）
    - あと、指の計算がどうしてもでかくなる。（ボーン数60！）

> まとめると、Anim Blueprint と Control Rig には、両手両足のIKエフェクタ(=IK末端)に合わせて、
> 
> - 両手両足の２ボーンIKを行う
> - 両手両足のIKの長さから、背骨周り(=体幹)を、なんちゃってでねじる
> 
> …をさせている、ということである。

## 物理回り

やはりプロシージャルアニメーションと言えば、アニメーションと物理の連携だろう。
物理はアクタ(Pawn)で行っており、

- アクタのルートコンポーネントは、Sphere Collision。
    - 力(Force)やトルク(Torque)は、ここにしか掛けていない。
- Skeletal MeshはSphere Collisionの子。
    - アクタの動きに100%くっついて動く。
- 両手両足のIKエフェクタ(=末端)は、アクタのTransformとは独立している。
    - 単純に、Transform型の変数を両手両足分の４つ持っているというイメージ（すべて、ワールド座標系）

こうしておけば、手足をワールド位置に固定したまま体(アクタ)が動く状態になる。

力やトルクの釣り合いは、IKルート(肩や股関節)とIKエフェクタ(手首や足首)との距離をベースにしたバネとダンパー（つまりサスペンション）で作ってある。

- IKが長いと、アクタのIKルートの位置に、IKエフェクタの方向に引っ張る力とトルクが加わる。
- IKが短いと、アクタのIKルートの位置に、IKエフェクトから離れる方向に力とトルクが加わる。

という形である。
下のGIFアニメは、これらを説明したもの。

![20210426_01_ControlRig.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358170/0355928e-fcb2-4b74-0a79-0026a600ed79.gif)

- 左側：物理だけ動いている状態（Control Rigを使っていない=アニメーションしていない）
    - 左手のIKエフェクタ(オレンジ色の〇)の動きで両手両足のバネの長さが変化し、アクタの釣り合いの状態がそれに合わせて動く様子。
- 右側：物理＋Control Rig
    - 左側の状態に加えて、IKエフェクタの位置に手足をIKで伸ばす。
    - 体幹(spine等)もなんちゃってでねじってある。

> なお、左右ともIKエフェクタの動きが同じなのに、オレンジ色のBOXで示したアクタの動きが異なって見える。
> これは、Control Rigによって体幹のねじりを作っているので、その分だけIKルート(肩や股関節)の位置が変化するためである。
> このねじり量は、なんとなく目分量で調整したもので、ノウハウも何もなく、単なる勘である。