【UE5】AnimGraph をいちから読み解く【初心者向け】

本稿では、Unreal Engine(以下 UE) 5 のサードパーソンテンプレートに含まれているアニメーションブループリント(ABP_Manny)の内容を詳しく読み解いていきます。
アニメーションブループリントは、AnimGraph とイベントグラフのふたつの機能を持っていますが、本稿では AnimGraph のみ扱います。

環境は以下。

Unreal Engine 5.3.1 および 5.4.2
Windows 11 Home
Visual Studio 2022

もくじ


テンプレにアニメーション追加しようと思ったけど、ひとつも分からん

※タップまたはクリックすると大きい画像で表示します。

UE5 のプロジェクトをサードパーソンで作成して、ABP_Manny を開いてみたんですが、AnimGraph がもう既に意味不明でした。
移動やジャンプはできますが、これに近接攻撃やパルクールのような動きを追加したい場合に、どうしたらいいのか分かりません。
ひとつひとつ地道に調べて、使い方を覚えていくしかなさそうです。


そもそも、ABP_Manny がどこにあるのか分からない。

UE 自体をほとんど触ったことがない方のために、ABP_Manny にアクセスするまでの手順を説明します。
長いので、読みたい方は以下のスポイラーを選択して内容を表示してください。

ABP_Manny の AnimGraph を確認するまでの詳細な手順を表示する
1. Unreal Engine のインストール

Unreal Engine 5.3.1 または 5.4.2 がないならインストールします。
インストール済みなら次へ。

インストール方法は公式にドキュメントがあるので、上記ブログカードのリンク先を参照してください。
バージョンは 5.3.1 か 5.4.2 をインストールします。

バージョンがちょっと違うだけで画面のレイアウトが変わったり、操作が変わったりするので、他のバージョンでは本稿の説明通りに進められなくなる可能性があります。バージョンはできるだけ一致させた方が良いです。
2. Unreal Engine を起動

インストールした直後なら、以下のような画面になっていると思います。

※タップまたはクリックすると大きい画像で表示します。

画像内に書かれていますが、赤枠で囲った位置にあるボタンを押します。
そのまんま「起動」と書いてあります。
※ボタンの右端にある「▼」は押さないでください。

Unreal Engine がバージョンアップすると、「起動」が「アップデート」に変わったりしますが、インストール直後なら「起動」になっているはずです。
3. スプラッシュ画面が消えるまで待つ

「起動」を押すとスプラッシュ画面が出てきます。

※タップまたはクリックすると大きい画像で表示します。

スプラッシュ画面が消えるまでひたすら待ちます。

インストール直後の場合は、ないと思いますが、シェーダーコンパイルやアニメーション圧縮が始まると数十分待たされることもあります。
極まれにスプラッシュ画面から進まなくなることがあります。
1時間待っても変化がないなら強制終了して、Unreal Engine を起動し直します。
スプラッシュ画面の下部に、「初期化中…10%」や
「シェーダーコンパイル中…20%」などのログが表示されているので、ここを見て進んでいるか、止まっているかを判断します。
4. プロジェクトブラウザでプロジェクトを作る

※タップまたはクリックすると大きい画像で表示します。

プロジェクトブラウザ内で以下の順に操作を行います。

  1. 左側にある「ゲーム」を選択。
  2. 中央上部にある「サードパーソン」を選択。
  3. 右側にある「C++」を選択。
  4. 左側下部にある「プロジェクトの場所」で任意のフォルダを選択。
  5. 右側下部にある「プロジェクト名」に任意の名前を入力。
    ※ここでは AnimGraphTest などが無難。
  6. プロジェクト名の下部にある「作成」を押す。
5. コンテンツドロワーで ABP_Manny を探す

※タップまたはクリックすると大きい画像で表示します。

UE エディタが開いたら、左下に注目。


こちらは UE エディタの左下部分を拡大した画像です。
「コンテンツドロワー」と書かれたタブがあるので、クリックします。

環境によっては、コンテンツドロワーが UE エディタにドッキングしている場合があるかも知れません。
その場合、タブをクリックする必要はありません。

※タップまたはクリックすると大きい画像で表示します。

※タップまたはクリックすると大きい画像で表示します。

上記の画像のように、コンテンツドロワーがニュッと出てきたら、コンテンツドロワーの上部にあるパスに注目。

※タップまたはクリックすると大きい画像で表示します。

コンテンツドロワーの上部に、右側ペインで表示しているフォルダへのパスが表示されています。
これは Windows のフォルダのパスではなく、UE エディタ内でアセットを参照するための特殊なパスです。

このパスが下記と一致するよう、左側ペインにあるフォルダをたどります。

All > コンテンツ > Characters > Mannequins > Animations >

上記のパスにたどり着いたら、右ペイン内に ABP_Manny があります。

6. ABP_Manny を開いて AnimGraph タブを選択

※タップまたはクリックすると大きい画像で表示します。

デフォルトでは「イベントグラフ」が表示されていると思います。
イベントグラフを見ることはないので、「イベントグラフ」タブの右上にある小さい×ボタンを押して閉じてしまっても構いません(マウスオーバーすると表示されます)。

イベントグラフの隣に「AnimGraph」タブがあると思います。
AnimGraph」タブをクリックします。

AnimGraph がない、間違って閉じてしまったとき

AnimGraph タブがない場合は、画面内に「マイブループリント」タブがないか探します。
もし「マイブループリント」タブがない場合は、メニュー > ウィンドウ > マイブループリント を選択することで、画面内に表示されるようになります。

※タップまたはクリックすると大きい画像で表示します。

「マイブループリント」タブを見つけたら、タブ内で アニメーショングラフ > AnimGraph を探します。
この AnimGraph をダブルクリックすることで、AnimGraph の編集画面を表示できます。

※タップまたはクリックすると大きい画像で表示します。


「ABP_Manny の AnimGraph を確認するまでの詳細な手順」は以上

ひとつずつ解き明かしていく

アニメーションブループリントとは?

UE 初心者が読むことも想定しているため、細かい話に入る前に、大まかな話をします。
アニメーションブループリントの概要について知りたい方だけ、以下のスポイラーを選択してご覧ください。

アニメーションブループリントの概要を読む
アニメーションブループリントには、おおまかに2つの機能があります。

1. ステートマシンでアニメーションの遷移パターンを作る。
2. ブループリントで遷移に必要なパラメータを制御する。

1. ステートマシンでアニメーションの遷移パターンを作る。

AnimGraph は、アニメーションのステートマシンを構築するためのエディタです。
ステートマシンは、ステート(状態)の移り変わり(遷移)を扱う仕組みです。
UE では AnimGraph を使うことで「どのような条件のときに、どのステート(アニメーション)に遷移するか?」を構築し、ステートマシンによるアニメーションができます。

Unity のアニメーターコントローラーと似たようなもので、細かい機能が違います。
広義ではどちらもステートマシンです。

ステートマシンでは、状態が遷移するときに、様々なパラメータを使います。

パラメータとは、
・キャラクターが空中にいるか?
・地面の上に立っているか?
・ダメージを受けているか?
・攻撃中か?
・どれくらいの速度で移動しているか?
…などのアニメーション制御に必要な値のことです。

このパラメータはアニメーションブループリントに追加したり、C++ に追加したりなどしたもので、それを UE のステートマシン ≒ AnimGraph で参照します。

パラメータ、遷移条件、ステートの3つの要素を駆使して、意図したタイミングで意図したステートに切り替わるように組み立てたデータをステートマシンが処理してくれます。
AnimGraph では、前述のステートマシンの3つの要素に加えて、AnimGraph 専用のブループリントを使うことができます(AnimGraph が難解なのはこの追加機能のせい)。

ステートマシンの例

上記の画像を例にすると、

何もしていないときは「待機」
移動量が増加したら「移動」へ遷移。
移動量がゼロになったら「待機」へ戻る。
空中にいるなら「ジャンプ」へ遷移。
着地したら「着地」へ遷移して「待機」へ戻る。

…というような遷移パターンになっています。

ステートは矢印の方向にのみ遷移します。
「今のステートから矢印の方向に遷移できるか?」を判断するときに、パラメータを参照します。

今のステートが「待機」なら、「移動量」パラメータを見て、ゼロより大きければ「移動」へ遷移し、今のステートが「待機」から「移動」に切り替わります。
今のステートが「移動」なら、「移動量」パラメータを見て、ゼロなら「待機」へ遷移します。
「移動」は「移動攻撃」と「ジャンプ」にも遷移できるので、「攻撃中かどうか?」のパラメータを見て、攻撃中なら「移動攻撃」に遷移します。
「ジャンプ中か?」「落下中か?」のパラメータを参照して、「ジャンプ」に遷移できるなら遷移します。

したがって、遷移条件はそれぞれの矢印に割り当てることになります。

ステートマシンは状態が遷移するものなら何に使っても良いのですが、アニメーションでよく使われます。
本来なら、例えば UI が状態によって処理を切り替える必要があるなら、UI がステートマシンを持っても構いません。
ただ、UE では AnimGraph で使うものです。

2. ブループリントで遷移に必要なパラメータを制御する。

パラメータの制御には、EventGraph (イベントグラフ) を使うことができますが、イベントグラフについては当ブログでは扱いません。
AnimGraph の調査の過程でイベントグラフを参照することはありますが、最低限にとどめます。

イベントグラフでブループリントを使ってパラメータを変更するのが一般的ですが、私がエンジニアなので C++ を使う場合はどうしたら良いのか?を学習するため C++ を使います。
そちらについては別の記事で扱う予定です。
C++ の方が処理が速いので、ブループリントでパフォーマンスに問題がある場合は C++ で1から作り直すことがあります。
重要なのは、アニメーションブループリントのパフォーマンスに重大な問題がある場合や、ブループリントが複雑になり過ぎて保守が困難になった場合、作業を効率化するのにどうしても必要な場合など、明確な理由がある場合にのみ C++ で作るという点です。
C++ で作るのは時間がかかる場合が多いのと、エンジニア以外が扱えなくなるので、業務でやるなら、それ相応の理由が必要です。


Locomotion (ロコモーション)

ロコモーションとは、移動(歩く、走る、旋回など)に関わるアニメーションの総称です。

ABP_Manny の AnimGraph を開くと、2つの Locomotion が並んでいるのが分かります。
左がステートマシン、右がノードです。

左にあるステートマシンの詳細は隠ぺいされています。
ステートマシンの詳細を確認するには、ダブルクリックする必要があります。


Locomotion ステートマシン

※タップまたはクリックすると大きい画像で表示します。

Locomotion ステートマシンの中を覗いてみます。
Locomotion ステートマシンをダブルクリックすると、ステートマシンっぽいグラフが表示されます。

↑の画像では余計な情報が多いので、重要な部分だけ抜き出すと以下になります。

Entry → Idle ⇄ Walk/Run

Locomotion ステートマシンは Idle(待機)と Walk/Run(歩く、または、走る)の2つのステートだけ持っていることが分かります。

ステートマシンの評価は Entry から始まります。
Entry から Idle に向かって矢印が伸びているので、そのまま Idle に行きます。
Idle に遷移するための条件はありません。
Entry に来たら必ず Idle に遷移します。

Idle と Walk/Run はお互いに矢印が伸びています。

1. Idle から Walk/Run に遷移する。
2. Walk/Run から Idle に遷移する。

Locomotion ステートマシンは、このどちらかの遷移しか行わないということになります。

これらの矢印は、上下に丸いアイコンが付いていますが、遷移条件を設定していると、このアイコンが付きます。
アイコンをポイントすれば遷移条件が表示されます。

↑の画像にある「トランジションルール」とは、「遷移条件」のことです。
「遷移条件」が一致したときだけ、矢印の方向へ進む…ということになります。

遷移条件は ShouldMove という名前の何か…を使って行われることが分かります。

ShouldMove は、日本語にすると、「移動するべき」となります。
NOT ShouldMove の NOT は否定の意味なので、「移動するべきでない」となります。

Idle は「待機」
Walk/Run は「歩く/走る」

「移動するべき」とき、「待機」から「歩く/走る」へ遷移する。
「移動するべきでない」とき、「歩く/走る」から「待機」へ遷移する。

Locomotion ステートマシンの遷移処理についてイメージはつかたので、まだよく分かっていない ShouldMove について調べてみます。


ShouldMove は何?

ShouldMove は遷移状条件に設定している「何か」なので、遷移条件を詳しく見てみます。
矢印の上にある丸いアイコンをダブルクリックすると、遷移条件を設定しているブループリントが表示されます。

そこに ShouldMove があるので、クリックして「詳細」を確認。

※タップまたはクリックすると大きい画像で表示します。

ブループリントの変数ですね。
「変数とは何か?」…は、知らなくても問題ありません。

マイブループリント > 変数 > Essential Movement Data で定義されています。
※マイブループリントが見当たらない場合は、こちらのスポイラーを展開して最後の方(ABP_Manny の AnimGraph を確認するまでの詳細な手順を表示する > AnimGraph がない、間違って閉じてしまったとき)をご覧ください。

ShouldMove は Boolean(ブーリアン)の変数なので、True(真)か、False(偽)か、2つの状態だけ持ちます。

ShouldMove の値が変わったときに、Idle ステートと、Walk/Run ステートの状態が切り替わります。
ShouldMove のような変数の使い道を理解するには、以下の2つのステップで調査を進めます。

  1. 変数の値を変更している場所を突き止める。
  2. 変数の値を変更する理由(条件)を理解する。

⇒ 変数の使い道が分かる。

まず、1について調べます。


ShouldMove の値を変更している場所はどこか?

変数がどこで使われているかは、検索できます。

Ctrl + F で検索欄を開き、ShouldMove と入力して Enter

Set 変数名 と書かれているところで値を書き換えています。
書き換えている場所は、そのすぐ上に表示されています。

ShouldMove は「イベントグラフ」のどこかで値を書き換えているようです。
検索結果をダブルクリックすることで該当箇所を確認できます。

※タップまたはクリックすると大きい画像で表示します。

検索結果の Set ShouldMove をダブルクリックしたところ、イベントグラフの↑の画像のブループリントが表示されました。


ShouldMove の値を変更する理由(条件)は?

※タップまたはクリックすると大きい画像で表示します。

↑の画像のブループリントを見た感じ、移動のための入力を行い、移動量が閾値を超えることで、 ShouldMove の値が True になるようです。

ゲームパッドを使う場合、サードパーソンシューターのキャラクターは、左のアナログスティックを倒したときに、倒した方向に移動します。
※ボタン割り当てを変更できるゲームもありますが、通常はそうなります。

アナログスティックは人の指先では感知できないほどのわずかな入力も検出できます。
そのわずかな入力でキャラクターが移動してしまうと、ゲームをプレイするユーザーは「何もしてないのに勝手に移動した。」と感じることになります。

そのため、ある程度アナログスティックを倒すまでは移動しないようにする必要があります。
この「ある程度」というのが、移動量の閾値です。

※タップまたはクリックすると大きい画像で表示します。

↑の画像の中にある Ground Speed > 3.0 という条件が、その閾値を判定している処理になります。
もうひとつの Get Current Acceleration は、入力の加速度を調べていますが、これは 0 より大きいかどうかだけ判定しているので、閾値とは関係ありません。

2つの条件を合わせると、以下のようになります。

移動のための入力がある、かつ、 Ground Speed の値が 3.0 より大きいとき、 ShouldMove が True(真)になる。
それ以外は False(偽)になる。

移動のための入力はアナログスティックとは限りません。
キーボード操作の場合、移動のための入力は「押す」か「押さない」かの2値になります。
※アナログ入力を検出できる珍しいキーボードもあるかも知れませんが、一般的ではないので除きます。

入力が「ある」か「ない」かしか見ていないのは、アナログスティックでも、キーボードでも、どちらを使っていたとしても、この処理で判定できるからです。
これで対応できない状況もあると思いますが、入門者向けのテンプレートとしては、これで十分です。
※作るゲームが明確になり、操作感を突き詰めていく段階になったときに、この処理では対応できなくなると思いますので、そのときに「改造」すれば良いです。

Ground Speed ってなに?」と思うかも知れませんが、直訳すると「地上の速度」になります。
ジャンプ中や落下中をのぞいた、地面の上や、何らかの床の上、足場の上にいるときの移動スピードのことだろう…という推測ができます。

ShouldMove については分かったので、 Ground Speed については掘り下げません。
気になるようであれば、ShouldMove と同じように検索して調べてみてください。

以下はゲームデザインに関する補足です。
興味がある方は、スポイラーを展開してご覧ください。



「ある程度」とはどの程度?
ゲームをデザインする上でよく問題になるのは、この「ある程度」という部分です。
ゲームの調整はほとんど、この「ある程度」の調整です。

どれくらいアナログスティックを倒せばキャラクターが移動するべきか?…は、人によって感覚が変わります。
ほんのちょっとアナログスティックを倒すだけで移動した方が心地よいと感じる人もいれば、完全に倒したときに移動した方がしっくりくる人もいます。
場合によっては、上下左右が反転していた方が良いという人もいます。
ゲームを作る側が「心地よい」と感じるものは、そのゲームをプレイするユーザーにとっても「心地よい」かどうかは、作る側には分かりません。
※困ったことに、ここを勘違いしている開発者は本当に多いです…。

これを理解しているかどうかで、多くの人が遊べるゲームを作れるかどうかが決まります。
※理解はしていても、主に納期(予算)の都合で対応できないことが「よくあります」。

この調整が上手いゲームは、多くの人が「心地よい」と感じるバランス調整が上手いです。
そのバランス調整のために、予算をかけて、幅広いユーザーに向けたテストをして、アンケートを取り、アンケートを分析した上で、チーム内で議論しながら調整を繰り返していたりします。
このバランスは、ゲームのジャンル、ターゲットにしているユーザー、その時代の流行…などによって、いくらでも変わります。

バランス調整が必要なところは、操作感だけではありません。
無数にあります。
ゲームの難易度もそうです。

ゲームを作っているうちに、何が正しいか分からなくなる…という人がいますが、それは正しいです。
分からないから、調べて、分析して、分かる部分を増やしていくことが重要になります。
分かる部分を絞り込み、調整しやすくするために、ゲームの対象者(ターゲット)を決めます。
どういうタイプの人が「心地よい」と感じやすいゲームにするか?…を決めるのが、このターゲットの設定です。

調整に十分な時間(予算)をかけられることは稀です。
時間をかければかけるほど、人件費や設備費で予算が減ります。
優秀なスタッフを集めたのにクソゲーができあがってしまう理由は、方針が間違っているか、お金の問題です。
方針が正しくても、十分な時間がなければクソゲーになり、時間があっても方針がブレていればクソゲーになります。


Locomotion ステートマシンの Idle ステート

Idle から Walk/Run へ「遷移する条件」は分かりました。
あと分かっていないのは、「Idle と Walk/Run ステートで何をしているのか?」です。

AnimGraph の中にあるステートマシンを評価した結果、行きつく先は Output Pose です。
アニメーションのどの位置(フレーム)を再生するのかをステートマシンで評価して、今ゲームが処理している1フレームで表示するべきアニメーションの1コマを決めます。
それが Output Pose です。

なので、Idle や Walk/Run など、ステートの中では、何らかのポーズを決めているはずです。

Idle ステートをダブルクリックすれば、Idle ステートが何をしているのかが分かります。

↑の画像は Idle ステートをダブルクリックして遷移した画面です。
※クリックするかタップすると大きい画像で表示できます。

MM_Idle → Output Animation Pose

アニメーションシーケンスの MM_Idle を再生しているだけです。

Output Pose と Output Animation Pose は何が違うの?

Output Animation Pose は各ステートの最後に配置します。
ステートマシンの中にあるステートの出口が Output Animation Pose です。
Output Animation Pose は、更に別の Output Animation Pose とブレンドする場合があります。
色々ブレンドした結果が Output Pose に出力されます。
ステートの出口が Output Animation Pose で、AnimGraph の出口が Output Pose です。

MM_Idle はサードパーソンテンプレートのマネキンで作られた待機アニメーションです。
デフォルトではアニメーションブループリント編集画面の右下「アセットブラウザ」にあります。
ここからドラッグ&ドロップすることで、ステート内に配置できます。
※本稿は読み解くのが目的ですので、編集はしません。

アセットブラウザが見当たらない場合は、メニュー>ウィンドウ>アセットブラウザ を選択することで表示できます。


Locomotion ステートマシンの Walk/Run ステート

Idle ステートと同じように、Walk/Run ステートをダブルクリックすることで、ステートの中身を確認できます。

こちらは Idle ステートと違い、アニメーションシーケンスをそのまま Output Animation Pose に繋いでいません。
ブレンドスペースと呼ばれるものを使っています。

ブレンドスペースは簡単に言うと、複数のアニメーションシーケンスを混ぜ合わせる機能です。
Walk/Run ステートで混ぜ合わせるのは、歩くアニメーションと走るアニメーションです。
どれくらい混ぜるか?を決めるのが、 Ground Speed です。

Ground Speed はキャラの足が床や地面に着いている状態での移動スピードです。
したがって、移動スピードによって、歩くアニメと走るアニメの混ざり方が変わります。
移動スピードが遅いときは、歩くアニメに近くなり、速いときは走るアニメに近くなります。

ブレンドスペースには、1軸と2軸があり、Walk/Run ステートで使われているのは1軸のブレンドスペースです。
デフォルトでは2軸のブレンドスペースになります。
1軸のブレンドスペースを作成したいときは、アニメーション>レガシー>ブレンドスペース1D を選ぶ必要があります。

本稿ではブレンドスペースについては、これ以上は触れません。
公式ドキュメント参照。

ここまでで、AnimGraph では、アニメーションシーケンスの再生方法が2種類あると分かりました。

  1. 1つのアニメーションシーケンスを再生することができる。
  2. ブレンドスペースで複数のアニメーションシーケンスを合成したものを再生することができる。


Locomotion ノード

Locomotion ステートマシンについては分かったので、また AnimGraph の最初の画面に戻ります。
次は、Locomotion ステートマシンの右隣りにある、Locomotion ノードについて調べます。

厳密に言うと、Locomotion ノードというノードはありません。
これは「キャッシュされたポーズ」に Locomotion という名前を設定したものです。


キャッシュされたポーズとは?


このノードは、Animation > Cached Poses カテゴリーにあります。

※タップまたはクリックすると大きい画像で表示します。

※タップまたはクリックすると大きい画像で表示します。

AnimGraph の何も配置していないところを右クリックすることで、AnimGraph に配置できるノードの一覧が表示されます。
ここから選ぶことができます。

これは、左にある Locomotion ステートマシンの結果をキャッシュ(メモリに保存)しておくためのノードです。
キャッシュしておくことで、ABP_Manny の AnimGraph 内ならどこでも Locomotion ステートマシンの「結果」にアクセスできます。

「結果」というのは、ステートマシンで様々なパラメータを参照して遷移先のステートが決まった状態を指します。
Locomotion ステートマシンに遷移するわけではなく、Locomotion ステートマシンで処理した結果をキャッシュします。

この仕組みを使うことで、複雑になりがちなステートマシンを綺麗に分かりやすく作ることができそうです。

例えば、「武器で攻撃するステートマシン」を作ったときに、このノードでキャッシュしておけば、AnimGraph 内の好きな場所から、「武器で攻撃するステートマシン」の「結果」に遷移できるようになるということになります。
そうすることで、「武器で攻撃するステートマシン」が必要になる度に、同じステートマシンをコピペする必要がなくなり、コピペしないよう巨大で複雑なステートマシンに含めておく必要もなくなります。
巨大で複雑なステートマシンとは別の場所に作っておいて、必要なときに呼び出すだけで済みます。

巨大で複雑なステートマシンが引き起こす問題について興味がある方は、以下のスポイラーを選択して内容をご覧ください。


ダメなステートマシンが引き起こすトラブル
ステートマシンは何も考えずに作ると、ステートが複雑に絡み合い、何をしているステートマシンなのかを把握するのが非常に困難なものが出来上がります。


この画像は UE 公式フォーラム「Cleaning Up State Machine Spaghetti」スレッドにあります。

このような「ダメな」ステートマシンに新しくステートを追加したり、遷移の仕方を変更する必要が出た場合、複雑すぎて理解できずに詰みます。
チームだと別の人が担当する場合があるので、理解できずに変更を諦めることになったり、作り直すことになるかも知れません。
理解しない状態で無理やり修正すると、ほぼバグります。
分かりやすいように作っておけば、追加も修正も少ないコストで対応できます。

ステートマシンに関しては、結果をキャッシュする仕組みを使うことで、攻撃、防御、ダメージ…などの意味のある単位でまとめておくことができるので、シンプルで見やすいステートマシンを作ることができるかも知れません。

※この時点では学習中ですので、そうなるはずだ…という推論です。

ステートマシンをキャッシュしたい場合は New Save cached pose… を選び、そのノードに接続します。

※タップまたはクリックすると大きい画像で表示します。

ノードの名前」は変更できます。
分かりやすい名前を付けた方が良いです。

ロコモーションステートマシンの結果をキャッシュするなら Locomotion
近接攻撃ステートマシンの結果をキャッシュするなら MeleeAttack
…など。


キャッシュしたステートマシンの結果にアクセスしているところは?

New Save cached pose… を使って、キャッシュしたノードを使いたい場合は、Use cached pose ‘ノードの名前‘ を選びます。

サードパーソンテンプレートの ABP_Manny でどのように使われているのかを確認することで、使い方が分かるかも知れません。

※タップまたはクリックすると大きい画像で表示します。

ABP_Manny の AnimGraph を開くと、Locomotion ステートマシンと、Saved cached pose ‘Locomotion’ ノードが繋がっています。
↑の画像は、この記事の冒頭でも登場しましたが、赤枠で囲った中のことです。

Locomotion ステートマシンの結果をキャッシュ(保存)していますが、この「キャッシュ」をどこで使っているのか?…については、まだ調べていません。

ABP_Manny の AnimGraph にあるステートマシンは Locomotion と Main States の2つだけです。
「キャッシュ」を使っているのは、どちらかのステートマシンの中ということになりそうです。

Locomotion ステートマシンの中で Locomotion ステートマシンの結果にアクセスする…というのは、エンジニア視点だと循環参照になってフリーズしないか心配になる設計なので、本能的に避けます。
Locomotion ステートマシンの中で「ない」なら、Main States の中だろう…と予想できます。


Main States ステートマシンの中を見る

Main States ステートマシンの中を調べ、Locomotion ステートマシンのキャッシュを探してみます。

※タップまたはクリックすると大きい画像で表示します。

AnimGraph の Main States ステートマシンをダブルクリック。

※タップまたはクリックすると大きい画像で表示します。

Main States 直下にはないので、とりあえず、Locomotion ステートをダブルクリックして、更に奥へ。

ありました。

左側にあるノード Use cached pose ‘Locomotion’ が Locomotion ステートマシンのキャッシュです。
Main States ステートマシンの Locomotion ステートに遷移することが決まったら、Locomotion ステートマシンのキャッシュが使われることになります。
キャッシュはステートマシンの結果を保持しているので、Locomotion ステートマシンを評価したのと同じ結果が得られることになります。

キャッシュを使っているのが一か所だけだと、キャッシュの有用性が分かりにくいです。
2か所以上でキャッシュを使ってみないことには、「なんでこんなややこしいことしてるの?」と思ってしまいます。


キャッシュを使わない場合はどうなるのか?

キャッシュの有難みを理解するために、具体例を考えてみます。

ステートマシンの中に、別のステートマシンを作ることができます。
これを利用して、Main States > Locomotion ステートの中に、Locomotion ステートマシンをコピペします。

※クリックまたはタップすると大きいサイズで表示します。

キャッシュを使わなくても、これで問題なく動作します。
キャッシュを使う場所が1つしかないなら、これでも問題ありませんが、ABP_Manny が Use chached pose ‘Locomotion’ を使っているのは、ここだけではありません。

Main States > Land ステートの中でも使っています。

※クリックまたはタップすると大きいサイズで表示します。

ここにあるキャッシュも Locomotion ステートマシンをコピペして繋ぎ変えます。

※クリックまたはタップすると大きいサイズで表示します。

これによって、以下の3か所に、中身が同じ Locomotion ステートマシンが存在することになりました。

  1. AnimGraph のトップ
  2. AnimGraph > Main States > Locomotion ステート内
  3. AnimGraph > Main States > Land ステート内

中身は同じですがコピーして複製したものなので、どれか1つに変更を加えたとしても、残りの2つには何も影響しません。
仮に、Locomotion ステートマシンに機能を追加する必要が出たとします。
その場合、コピペした3か所全てを修正する必要が出ます。

逆に、キャッシュを使った場合、Locomotion ステートマシンは1か所にしか存在しません。
残りの2か所は、Locomotion ステートマシンの結果をキャッシュしたものです。
Locomotion ステートマシンの結果が変われば、キャッシュの中身も変わります。
したがって、キャッシュを使えば1か所を修正するだけで済みます。

ステートマシンを修正したときに、無駄な作業を発生させないようにするには、キャッシュを上手く使うことが重要ということになります。


UE5 で追加されたステートエイリアス

※クリックまたはタップすると大きいサイズで表示します。

Main States ステートマシンのトップに戻ります。
ここまでスルーしていましたが、このステートマシン、おかしくないでしょうか?

※クリックまたはタップすると大きいサイズで表示します。

ステートマシンは Entry から評価が始まりますので、下にある2つのステートは Entry からたどることができます。
ところが、上にある3つのステートは、下にあるどのステートとも線で繋がっていないので、たどりようがありません。

よく見ると、To Land と、To Falling は頭についているアイコンが違います。
名前も To(~へ)と…どこかへ遷移するかのような名前がついているので、なんとなくステートとは違うものだろう…という予想はできます。





予想通り、To Land と、To Falling は、UE5 で追加されたステートエイリアスと呼ばれるものです。
AnimGraph を見ても、上と下のステートマシンの間には隙間があり、線は繋がっていませんが、実はこの2つは他のステートと繋がっています。


どう見ても Locomotion ステートで止まる件

※クリックまたはタップすると大きいサイズで表示します。

Main States ステートマシンはパッと見、Locomotion ステートから他のステートに矢印が伸びていないので、「どうやって Land や Jump に遷移するんだ?」と思ってしまいます。
ステートマシンは Entry から評価が始まるので、Entry → Locomotion と遷移して、そこで止まってしまうように見えます。

To Land と To Falling がどのステートと繋がっているか?は、それぞれをクリックして「詳細」を見ることで確認できます。

※クリックまたはタップすると大きいサイズで表示します。

※クリックまたはタップすると大きいサイズで表示します。

文字だと分かりにくいので、図にします。

※クリックまたはタップすると大きいサイズで表示します。

To Land と To Falling がどこのステートと繋がっているのかが明確になりました。
ただ、どっちの方向に遷移するのか?が分かりません。

ステートエイリアスには、遷移条件も遷移する方向も指定できないので、おそらく、双方向に繋がるのではないかと思われます。
※遷移条件については後述します。

※クリックまたはタップすると大きいサイズで表示します。

こうなりますが、他のステートの矢印の方向をたどると、遷移する方向は自ずと決まりそうです。


To Falling を経由する遷移パターン

Entry からたどってみます。

Entry → Locomotion To Falling
Entry → Locomotion To Falling → Jump
Entry → Locomotion To Falling → Fall Loop
Entry → Locomotion To Falling Land
? → To Land → Land To Falling

Jump と Fall Loop から To Falling に向かっている矢印はありません。
したがって、To Falling の遷移する方向は以下の3つです。

Entry → Locomotion To Falling
Entry → Locomotion To Falling Land
? → To Land → Land To Falling

この時点では、Entry から To Land に遷移するパターンが不明なのでモヤっとしますが、To Land への遷移方法は次の項で確認します。


To Land を経由する遷移パターン

Entry → Locomotion → To Falling → Jump To Land
Entry → Locomotion → To Falling → Fall Loop To Land

Land から To Land に向かっている矢印がないので、To Land を経由する遷移パターンは上記の2つだけです。


遷移条件は?

実際はこのようなステートマシンになっているということが分かりました。
ただ、ステートエイリアスへの遷移条件が分かりません。
これはおそらく、「ない」が正しいと思います。

ステートエイリアスへの遷移条件はなく、ステートエイリアスから他のステートへ遷移するときに、その遷移条件が評価されます。

以下は公式のドキュメントにある「ステートエイリアスを使わない場合の遷移図」ですが、これと一致します。

ステートエイリアスが間に入っているので分かりにくいですが、実際は以下のように繋がっていることが分かります。

Locomotion Jump
Locomotion Fall Loop

Jump Land
Jump Land

Fall Loop Land
Fall Loop Land

よく見比べてみてください。


おつかれちゃーん

ここまでで、AnimGraph の説明はほぼ終わりです。
あとは、スロットとコントロールリグについてですが、これらはどちらかというと、アニメーションモンタージュやシーケンサー、IKリグの制御に必要なものなので、簡単な説明にとどめます。


Slot (スロット)

※タップまたはクリックすると大きい画像で表示します。

※タップまたはクリックすると大きい画像で表示します。

アニメーションはスケルトンのボーンを回転させたり、移動させたりして行いますが、スロットは複数のボーンをまとめたものです。
上半身だけ、右腕だけ、左足だけ…など、複数のボーンに別のアニメーションを割り当てたいときに使います。

詳しくは公式のドキュメントをご覧ください。

アニメーションブループリントの仕組みを把握するため、サードパーソンテンプレートは使用せず、いちから AnimGraph を作ったことがあります。
その時はスロットノードの必要性が分かっていなかったので、繋いでいませんでした。
その状態でアニメーションモンタージュを作成し、再生したけど動かない…なんていうミスをして少し悩んだことがあります。

アニメーションモンタージュの動作には、最低限「DefaultSlot」を AnimGraph で繋ぐ必要があります。
新しくスロットを追加したら、DefaultSlot に加えて、追加したスロットを AnimGraph で繋ぐ必要があります。
それ忘れると、スロットを使ったアニメーションが再生されません。


Control Rig(コントロールリグ)

アニメーションブループリントは、ブループリントのシステムで動きますが、コントロールリグは別の仕組みで動くアニメーションです。
そのため、アニメーションブループリントでコントロールリグを使う場合、Control Rig ノードを AnimGraph に繋ぐ必要があります。

簡単に違いを確認できる方法としては、IKリグです。
以下は、AnimGraph の Control Rig ノードを繋いだ状態(IKあり)と、繋いでいない状態(IKなし)での比較になります。

IKあり
IKなし


エンジニアに質問:時間かけて勉強しなくても、エンジニアなら C++ で AnimGraph みたいなもの作れるでしょ?

C++ で似たような機能を作れるか?作れないか?と言われた場合、作れます。
作れますが、UE エディタの仕組みに合わせて作ろうとすると、スレートの仕組みを把握するための調査から始める必要があるので、とてつもない時間がかかります。
とてつもない時間をかけて、AnimGraph のような挙動をする C++ のプログラムを作る意味があるか?と言われると、ないと思います。

詳しく知りたい方はこちらをタップかクリックで開いてご確認ください。
既に AnimGraph という便利な機能があるのに、C++ をいじらないと修正できないような劣化版 AnimGraph を作る理由がないです(C++ の学習目的ならありですが)。

更に詳しく書くと以下のようになります。

1. データをコードに入れるべきではない。

AnimGraph やステートマシンのようなデータを効率よく作ることができるエディタがあるなら、それを使った方が良いです。
エディタが使いにくいなら修正すれば良く、似たようなものをいちから作るのは時間の無駄です。

コードはデータだけで処理できないことや、大量のデータをまとめて処理するために使うべきです。
コードに入れなくても良いものを入れるのは、コードのコンパイル時間も、コードを書く時間も無駄です。
コードに入れたデータを修正する度に、エンジニアがコードを変更して、コンパイルして、テストしなければならなくなります。
大抵の場合、そのデータが必要なのはエンジニアではなく、エンジニア以外です。

2. C++ で組むとエンジニアしか触れなくなる。

1. で記載しましたが、データを触る必要があるのは大抵の場合エンジニアではありません。

普通の規模のチーム開発では、データをコードに入れてしまった場合、データを修正する度に以下のような無駄な手間が発生します。

A. エンジニアに修正を依頼する。
B. エンジニアが作業時間を削って修正し、ビルドし、テストする。
C. エンジニアがビルドをアップデートするためバージョン管理アプリを更新する。
D. Jenkins などの CI/CD システムでビルドとデプロイが終わるまで待つ。
E. 終わったらローカルのビルドを更新してテストする。

テストしても直っていなかったり、新たなバグが発生する度に、エンジニアを拘束する必要があります。
エンジニアの手が空いていなくて、作業に取り掛かるまで何週間も待たなければならないかも知れません。
状況によっては、直さないままゲームをリリースすることになる可能性があります。
直す、直さないの決定権はリードやディレクター以上のチームで高い権限を持つ人たちになります。

3. C++ で組んでもゲームのパフォーマンスが向上する保証はない。

ブループリントのようにパフォーマンスが落ちることが確定しているわけじゃないので、検証するところから始めないといけなくなります。
純粋にめんどくさいです。

明らかに AnimGraph のパフォーマンスに問題があれば、何らかの対策は必要ですが、自前の AnimGraph を作っても改善するかどうかは疑問です。
AnimGraph でボトルネックになっているところを特定して、その部分だけ修正するのが精いっぱいじゃないかと思います。

・エンジン側の特定のコードがパフォーマンスを下げているなら、その部分のコードを修正する。
AnimGraph で使っている特定のアニメーションデータが重いなら、軽量化する。
AnimGraph のステートマシンの組み方に問題があるなら、問題がない組み方に直す。

4. エンジニア以外にお任せできるならそうすべき。

一般論として、エンジニアよりアートやデザイナーの方が、アニメーションを作るセンスもこだわりもあります。
コードはエンジニアが書くべきですし、アニメーションの構築はその専門家に任せるべきです。


エンジニアに質問:AnimGraph をコードで書かないなら学習する必要はないのでは?

あります。
理由は2つです。

1. 知らないと作業効率を高めるためのシステム設計ができない。
2. 知らないとアニメーション関連の不具合を解決できない。


1. 知らないと作業効率を高めるためのシステム設計ができない。

シーケンサーを除くと、アニメーションに関わる機能だけでも沢山あります。
(上記ブログカードのリンク先にあるページを親として、子ページ、孫ページまで含めると100ページを超えます…。)
これ全てを覚えないと、どんなシステムを作れば作業効率を高めることができるのか?が分かりません。

アーティストやゲームデザイナーが、類似の機能が既にあることを知らずに
「こういう機能を作って欲しい。」という要望を出して来ることがあります。

要望をもらったらエンジニアが詳しく調べる必要があります。
でないと、既にある機能の劣化版を作る…という無駄なことをしてしまいます。


2. 知らないとアニメーション関連の不具合を解決できない。

アニメーションがうまく動作しないときに、エンジニアに調査依頼が飛んで来ます。

アニメーションのデータに問題があるのか、アニメーションに設定したイベントに問題があるのか、AnimGraph に問題があるのか、ブループリントに問題があるのか、エンジン側のコードに問題があるのか、プロジェクト側のコードに問題があるのか、原因を突き止める必要があります。

オフラインのゲームなら、アニメーションで何らかの問題が出たときに調査するところは、上記くらいで済みますが、オンラインゲームだと更に調査範囲が広がります。

UE のアニメーションについて、一通り把握していないと原因を突き止めることができません。
場合によっては、インポート元の FBX の中身を調べる必要が出て来るかも知れません。

バグが出た時点では、どこが悪いのか?は分からないので、エンジニア以外で調べてもらって、それでも原因を突き止められない場合は、エンジニアが詳しく調査することになります。
あらゆる可能性を考慮して、徐々に問題の箇所を絞っていく必要があります。
最終的に問題を引き起こしていたのがコードの中にあるかも知れないですし、データの中にあるかも知れません。
両方が複雑に影響し合うことで、特定のタイミングで、特定の操作をしたときだけ起きるバグかも知れません。

本稿のアイキャッチ画像は Microsoft Copilot Designer で生成したものです。

以上

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です