
こんにちは。 ゲーム事業本部 エンジニアの岸下です。
今回は以前自分が記事でご紹介させて頂いたMoverプラグインと、UEの機能であるMotionWarpingを同時に使用する方法についてご紹介します。
(使用しているUEのバージョンは5.7になります。)
Moverの簡単な機能紹介は以前の記事をご参照ください。
目次
MotionWarpingとは
今回の記事はMoverとMotionWarpingの同時使用に関するものですが、本題に入る前にそもそもMotionWarpingとは何かについて軽く触れておきます。
ゲーム制作の中で、特定のモーションを行う際に、ゲーム上の何か(敵や壁等)に向かってキャラクターを移動させたい場面があると思います。
よくあるシチュエーションだと、以下が挙げられます。
- 攻撃する際は敵に近づいてほしい
- 壁を登る際は壁のフチを掴むように移動してほしい
- ドアを開ける際はドアノブを掴むように移動してほしい
そういった際に「モンタージュ上に専用のNotifyを設定し、プログラム側から位置や回転の情報を与えてあげることで、キャラクターをそこまで動かすことができる」という物になります。
下記の公式のページで導入方法やサンプルが確認できますので、気になった方はこちらも併せて読んでみてください。
MotionWarpingの動作に必要な前提条件
続いて、MotionWarpingを動作させるのに必要な前提条件についてです。
MotionWarpingの導入自体はそこまで難しくないのですが、動作させるためにはいくつかの条件があります。
以下がその条件の一部になります。
- MotionWarpingプラグインが有効であること
- CharacterMovementComponentを使用していること
- 使用するモーションがRootMotionであること
- EnableRootMotionが有効化されていること
- シーケンスではなくモンタージュを使用していること
他にも、正しく動作させるためには「Notifyとコードで設定したWarpTargetNameが完全一致していること」等があります。
さて、今回ネックになってくるのは上記の条件の二つ目「CharacterMovementComponentを使用していること」になります。
MoverComponentはCharacterMovementComponentの代替となるコンポーネントですので、当然この条件は満たすことができません。
なぜCharacterMovementComponentでないと動かないのかというと、Root移動が関係しています。
「使用するモーションがRootMotionであること」「EnableRootMotionが有効化されていること」等の設定をちゃんと行っても、Moverを使用しているキャラクターではRoot移動が反映されません。
MoverとMotionWarpingを同時に使用するには
本題になります。
MoverとMotionWarpingを同時に使用するには…
PlayMontage (MoverActor)ノードを使用してモンタージュを再生するだけ!!

はい。これだけです。
試しにGameAnimationSampleで挙動を変えてみましょう。
このサンプルでは「AC_TraversalLogic」でPlayMontage (MoverActor)が呼ばれています。
ここを通常のPlayMontageでのみ再生するように変えてみます。
本来は、障害物を乗り越える際に正しい位置に補正されるのですが、それが働かず壁に埋まってしまうようになりました。

では元に戻してみます。
MotionWarpingが働くようになり、自然に乗り越えモーションが出るようになりました。

但し、このノードはBPでしか使用することができません。
また、
BPでキャラクターの挙動を作成している場合は、このノードを使用するだけで問題ありませんが、C++で挙動を書いている場合はもう少し掘り下げてあげる必要があります。
C++の場合
ではC++で先ほどのPlayMontage (MoverActor)と同じことをするにはどのようにすればよいのでしょうか。
PlayMontage (MoverActor)ノードの中身を見ていこうと思います。
こちらのノードはUK2Node_PlayMontageOnMoverActorというクラスで定義されています。
このクラスのcppを見てみると、コンストラクタでProxyClassとしてUPlayMoverMontageCallbackProxyというクラスが使用されているようです。

処理の中身はそちらにあるようなので、見てみましょう。
UPlayMoverMontageCallbackProxyにはCreateProxyObjectForPlayMoverMontageという関数があります。
この関数に最低限MoverとMontageを渡して呼び出すとPlayMontage (MoverActor)で再生した時と同じ結果が得られます。
なので、とにかく手っ取り早くMoverとMotionWarpingをC++で同時に使いたい!という場合は
UPlayMoverMontageCallbackProxy::CreateProxyObjectForPlayMoverMontage(キャラクターのMoverComponent, 再生したいAnimMontage);
という形でモンタージュを再生することで解決できます。
UPlayMoverMontageCallbackProxyは何をしている?
とはいえ、中で何を行っているか把握できていないと応用等できないので、どのような原理で動くようになったのか見てみましょう。
まずはクラスの説明が書かれているコメントの内容から読んでみます。
翻訳ソフトで翻訳してみると、以下のような事が書かれていることがわかりました。
ランタイムオブジェクトは、Moverアクター上でアニメーションモンタージュを実行する非同期ブループリントタスクノードへのプロキシとして使用されます。これは、親のUPlayMontageCallbackProxyを利用してアニメーションを実行すると同時に、モンタージュからのルートモーションを処理するためのレイヤードムーブを追加します。
ここで重要なのは「モンタージュからのルートモーションを処理するためのレイヤードムーブを追加します」という部分になります。
書かれている通り、UPlayMoverMontageCallbackProxyからモンタージュを再生すると、ルートモーションを処理することができるようになります。
そのために追加されているのが「LayeredMove」という物です。
LayeredMoveとは何か、公式ドキュメントから翻訳して引用になります。
レイヤードムーブとは、追加的で、通常は一時的な動きを表すオブジェクトのことです。例えば、アクターを反発させる一定の力、敵に向かって移動するホーミング力、あるいはアニメーションによって駆動されるルートモーションなどが挙げられます。 レイヤードムーブは、提案された動作を生成し、アクティブな動作モードに基づいてそれを実行します。複数のレイヤードムーブが同時にアクティブになることができ、他の影響と組み合わされます。レイヤードムーブの有効期間は、一定期間の場合もあれば、瞬間的な場合もあり、動作モードの変更後も有効です。 dev.epicgames.com
上記にある通り、LayeredMoveを使用することで、Rootモーションを動作させることができるようになります。
これを踏まえて、先ほどのUPlayMoverMontageCallbackProxyの中身を改めて確認してみます。
CreateProxyObjectForPlayMoverMontage関数は、PlayMoverMontage関数を呼び出しており、その中で処理が行われています。
まず最初にモンタージュの再生を行っています。

長いので少し省略しますが、以下のようにLayeredMoveに渡す情報を作り、

最終的にQueueLayeredMoveを呼び出しています。
![]()
これでLayeredMoveにRoot移動の情報が渡り、Root移動が有効になります。
また、Root移動が有効になった事でMotionWarpingも処理できるようになり、動作するようになる、という形です。
さいごに
以上、MoverとMotionWarpingを同時に使用する方法でした。
LayeredMoveは今回のようにRoot移動だけではなく、キャラクターを吹っ飛ばしたりもできるので、使い方を知っていると色々なところで応用できるのではないでしょうか!
UE公式が出しているサンプル(Mover Examples)にも、LayeredMove用のレベルがあるので、更に理解を深める際にはそこを確認してみると良さそうです。
最後まで読んで頂きありがとうございました。