【UE4】上半身と下半身のアニメーションを別々にしてコンボ攻撃のアニメーションをブレンドする


# 最初に

どうも、[ろっさむ](https://twitter.com/4_mio_11)です。

今回はUE4で`AnimMontage`を使用してアニメーションを再生している際に、どのようにして上半身と下半身、異なるモーションを用いてブレンドするのかをまとめようと思います。

この記事では`AnimMontage`の詳しい使用方法や実際の使い方に関しては紹介しません、ご了承ください。



# 目標

今回の目標はコンボ攻撃をしながら走った場合、足は走るために動き、上半身はコンボ攻撃の動きをする、というものです。ついでに止まってる時はコンボ攻撃アニメーションを優先して再生させます。

![ComboAttack_fix.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36899/f93f3c03-3b57-6795-f996-720f43532eb1.gif)



# 作り方



## まずは普通に再生してみる

シンプルに`AnimMontage`が再生された場合、アニメーションの上書きを行うなら以下のようになります。

![image-20201109223222989.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36899/8fd3115e-4a12-ed8c-c4e0-013e3b66415f.png)


ただし、この状態ですと

- **基本は`Locomotion`側でOutputされたアニメーションを再生**
- **スロットアニメーションに再生命令が入った時にはスロットアニメーションの再生が優先され、`Locomotion`側でのアニメーションは再生されません。**

つまりこの状態で走りながらコンボ攻撃アニメーションを再生すると、以下のようになります。

![ComboAttack00.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36899/8211835d-8c35-651e-63e1-a4f6a0b3c11c.gif)


見事に足が滑っていますね。



## ブレンドを行ってみる

走りアニメーションとコンボ攻撃アニメーションをそれぞれ、下半身と上半身に分けてアニメーションのブレンドを行う際には、`Layerd blend per bone`というノードを使用します。

![image-20201109224352352.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36899/5b18620f-d812-6779-eabe-793312be8c2d.png)


このノードの`BasePose`に`Locomotion`側でのOutputアニメーション、つまり走りアニメーションを繋ぎ、`BlendPoses0`にスロットアニメーションを繋ぎます。`Blend Weight 0`はデフォルトの数値のままとしておきます。

![image-20201109224540855.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36899/724e4a9d-18bc-02e9-5c86-8d98137bf429.png)


次に、`Layered blend per bone`のDetailsから`Layer Setup`を確認します。ここで`Branch Filters`の＋マークを押してmemberを追加し、`Bone Name`を入力します。この`Bone Name`はどのボーンから`BlendPoses0`を適用するか、という設定なので、使用しているモデルの腰あたりのボーン名を確認して入力しましょう。設定したボーン以下の子ボーンがブレンドされます。今回のモデルでは`body`以降をアニメーションブレンドさせたいと思います。

![image-20201109231433802.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36899/fca2f509-e185-9b71-e39b-638d2e447d26.png)



次に`Blend Depth`ですが、これは公式リファレンスでは単に「1」に設定してくださいとしか書いてありませんでしたが、この値は**どうやら `1.f / (float) BlendDepth` という式に使用**され、**設定したボーンから子ボーンにかけて`BlendDepth`の数だけ徐々に段階的にアニメーションの適用率を大きくする**ようです。

例えば、各数値を設定した場合は以下のようになります。

- `0`または`1`と設定すると`body`以降の子ボーンは全て`100%`ブレンド
- `3`と設定すると`body`は`33%`、`head`と`L_arm01`、`R_arm01`、`bust`は66%、それ以降の子ボーンは`100%`ブレンド
- `-1`と設定すると`body`以降の子ボーンは全て`0%`のブレンドとなり、アニメーションが再生されない

これを踏まえて今回は`3`と設定しておきます。走っている最中で腰部分が激しく動いているとグニャグニャ動いてるように見えて不自然なので、`body`のブレンド率は低めとします。

`Mesh Space Rotation Blend`に関しては、デフォルトだとブレンドするアニメーションのRotationがそのまま反映されます。ただ、その場合は攻撃アニメーションが誤った方向に回転したり、頭などが不自然に動いたりします。

なのでチェックをつけておきましょう。

`Mesh Space Scale Blend`に関しては、今回Scaleをいじるアニメーションを特に使用していないため、デフォルトのままにしておきます。以降のパラメータもデフォルトとします。



今回のモデルでは以下のような設定となりました。

![image-20201109235326430.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36899/9985d642-16c8-f16f-9700-efcd3e0f1ea3.png)


これで走りながらコンボ攻撃アニメーションが再生されるようになりました。

が、この状態だとスロットアニメーションが設定されてない場合、つまりコンボ攻撃アニメーションをしていない時は上半身がTポーズのそれになってしまいます。

![image-20201110001333040.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36899/518a0ea2-38f0-2c12-8a2d-759db02a014f.png)



なので、スロットアニメーションからアニメーション再生命令がでるまでは、`Locomotion`側でOutputしてるアニメーションを再生するようにします。



## Cached poseを使用する

最初の、`Locomotion`の次にスロットアニメーションを繋ぐことで、普段は`Locomotion`での結果が出力され、スロットアニメーションに再生命令が来た際はそちらを優先して出力するという仕組みを利用します。ただし、ABPの中で`Locomotion`を2つ以上繋ぐノードが存在する場合はPoseをキャッシュして、そのPoseを参照する形でノードを繋ぐ必要があります。

Poseのキャッシュには`New Save cached pose...`を選択します。

![image-20201109170520884.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36899/593a9bab-21ae-bf96-a13b-63ee5890c26b.png)



このキャッシュ用のノードに名前を設定しておきます。

![image-20201110002638617.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36899/d90a98ea-f799-5dcc-1842-4720ffb61c55.png)



作成したキャッシュ用のノードは検索にも名前で引っ掛かるようになります。

![image-20201110002757021.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36899/c4c248e4-31cc-0903-8c7f-22be03909952.png)



このキャッシュノードを使用して改めて組んだものがこちらです。

![image-20201110002735335.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36899/bfeb191d-aa43-8f04-77b9-3d64b9c05f60.png)


これで以下のように、走りながらコンボ攻撃アニメーションを再生できますし、立ち止まってもTポーズになることはありません。

![ComboAttack01.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36899/533eeac7-50a1-b0fa-7352-9f8c512bc179.gif)



この状態でも充分であればそれはそれで良いのですが、今回使用している攻撃アニメーションには足の動きもついているため、立ち止まっている時は足の動きは反映させるようにしておきたいと思います。



## Blend Poses by boolを使用してIdle時とRun時で分岐させる

この`Idle`時と`Run時`で処理を分岐させるために使用するのは`Locomotion`側でも使用しているアクターの移動速度用変数と、その**値によってブレンド時間を入れつつアニメーションを切り替える`Blend Poses by bool`ノード**です。

![image-20201110003256409.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36899/f3ad3d31-72ad-f116-46aa-e732e569c06a.png)


これは`Active Value`に繋いだ値が`true`なら`True Pose`を出力する見たままのノードです。

移動速度に関しては今回`Speed`という名前で定義し、`EventGraph`で取得しています。

![image-20201110003434996.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36899/9788ab5f-c6d0-aecd-c727-6dfcecae726c.png)


この`Speed`の値が`0`より大きい場合は移動していることになるので、これまで作ってきたノード群を繋ぎ、`Speed`が`0`なら前進でスロットアニメーションを優先で再生する状態に組みます。

![image-20201110003726005.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36899/ad409db7-f783-a478-a254-95f950ba1f34.png)




これで`Idle`時は攻撃アニメーションがそのまま再生されるようになりました！

![ComboAttack03.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36899/00123dc6-9dce-4b37-67ac-a0f8421cd699.gif)




# 参考

https://docs.unrealengine.com/ja/Engine/Animation/AnimHowTo/AdditiveAnimations/04_BlendSettings/index.html

https://answers.unrealengine.com/questions/336798/how-to-use-blend-depth-in-layered-blend-per-bone-n.html

https://answers.unrealengine.com/questions/387906/what-does-the-blend-depth-parameter-in-layered-ble.html?sort=oldest

https://unrealengine.hatenablog.com/entry/2015/02/20/220000

https://dawnarc.com/2018/04/ue4animation-blending-notes/