読者です 読者をやめる 読者になる 読者になる

当たったらどうすんだよ

当たらなければどうということはない

UE4のテンプレートに自分で作ったキャラを入れて動かしたい そのキュー:ランダム待機モーション

BlenderとZBで作った人物キャラの記事の途中ですが、とにかくUE4にキャラを入れて動かしたい!系のネタもひとつ投下しておきます。

タイトルの通り「待機モーション(アイドルモーション)をランダムに切り替えたい」のです!切に!痛切に!はしたないほどに!

実は以前に、まったく同じことを考えいろいろ調べて自分なりの方法を編み出し、コンテンツに実装したことがあります。その方法とは、歩き~走りのモーションをスピード変数などによってブレンドしてくれる「ブレンドスペース1D」を利用して、用意した待機モーションをすべて登録し、X軸を「Idle Variation」という名前の「整数の変数」にする、という仕組みでした。

しかし僅か一年ほどの時の流れの中で、もう少しマシな方法が見つかりましたので紹介したいと思います。いや、実はやってることはまったく同じなんだけどwブループリントの使い方とかが違うって感じです、はいw

必要な要素をブロック図にして考える

f:id:kanianthi:20160608230607p:plain

プログラム初心者は特にですが、こんな風にイラストレーターで手間をかける必要はありませんので、手書きのメモでも土に枝で描くでも構いませんのでブロック図を書いてやりたいことの概念を整理するクセをつけましょう。

というか、プログラマーでーすとかSEでーすなんて言ってるくせに、こうしたブロックダイアグラムが一切書けないだとか、書いてもらっても意味が分からないというひともけっこういます。残念ですがそれではコミュニケーションが成り立ちません。不思議な話ですが現実です。

少しそれました。

話を戻すと、

  1. 用意した待機アニメーションを切り替える仕組み→いいノードがあった
  2. 用意したアイドリングアニメの数→そのまま変数にする
  3. 一回のアニメーションを再生する時間(秒)→これも変数にする
  4. 経過時間を測る→Delta Timeという仕組みからうまいことやる

というような要素を組み合わせれば、ランダムに待機アニメを再生させることができそうです。流れとしては、

  1. アニメーションの切り替え(選択)
  2. 再生時間を管理して、既定の時間でリセットする
  3. 時間がリセットされたら、再びランダムにアニメーションを切り替える

という感じでいけそうですね。

実際にUE4でノードを組んでみる

ランダム待機アニメーションを実現するために改良しなければならないのはどのブループリントでしょうか?アニメーションを管理しているのは?

…そうアニメーションブループリントですね!(そのまんまや!)

というわけで早速開いてみます。
※サンプルプロジェクトでは「Statue AnimBP2」と複製リネームしています。

f:id:kanianthi:20160608232623j:plain

↑アニムグラフを修正して「IdleVariation」というステートを追加しました。画像ではまだ変更していませんが「Idle/Run」も「Walk/Run」に変更することにします。

このIdleVariationが待機アニメをランダム再生するためのステートです。このステートはキャラが停止しているとき、つまりSpeedがゼロのときに再生されれば良いのですが、実験してみたところ「スピードが2」を区切りに未満と超過で遷移させるといい案配でした。

それではステートの中身を見てみましょう。

f:id:kanianthi:20160608233205j:plain

↑が中身です。

中央にある大きなノードが「整数値でのブレンドポーズ」というノードです。なにやら難しそうですがやっていることはごく単純で、BlendPose0~と並んでいるそれぞれのソケットに接続されたアニメーションを、一番上にあるActive Child Indexという整数の値で選んで次のノードに渡すだけのものです。

このActive Child Indexを指定するための変数として「Idle Num」という整数値の変数を作りました。

またBlendTimeというのは、それぞれのアニメーションを別のアニメーションとブレンド(トランジジョン)させる時間指定をしているものです。

なおUE4でもそうですが、プログラムの世界では整数をinteger(インテジャー!)と呼び、浮動小数点数をfloat(フロート)と呼びます。はい、英語そのまんまですね。

というわけで、上記のノードはすたちゅーさん用に用意した4つの待機アニメーションを「整数値によるブレンドポーズ」に突っ込み「Idle Num」という変数で呼び出すというそれだけのモノです。特に複雑なことはなにもありません。

面倒くさいのはイベントグラフ

f:id:kanianthi:20160608235132j:plain

同じくアニメーションBPのイベントグラフにも改良を施さなければいけません。

まず経過時間を測るための変数として「Cureent Delta Time」を作成しました。変数の作成は「マイブループリント」タブの下にある緑色のボタン「+新規追加」などで行えます。

デルタタイムというのは前フレーム(ここでは処理)からの時間経過を秒で示しています。アニメーションBPでの処理とは「アニメーションを更新すること」ですから、走っていたキャラが停止すれば「walk/Run」から「IdleVariation」にアニメーションが遷移し「処理が走った」ことになり、デルタタイムが0にリセットされ、増えていくはずです(たぶん)。

なのでイベントグラフの先頭になる「イベントBlueprint Update Animation」ノードのすぐ後にセットで「Current Delta Time」を配置したのです。ここでいうセットはノードをセットすることではなくw変数に値を突っ込むことを指します。
※反対にゲットは変数から値を取り出すことです。

さらに、IsInAir?とSpeed値を取得する既存のノードに行く手前で「シーケンス」というノードを使って処理を分岐させました。

ランダムに整数値を取り出す処理

f:id:kanianthi:20160609001203j:plain

↑これがRandom Idle Animation Variablesです!かっけぇ!

  1. 変数Speedがゼロ(キャラが静止しているとき)か?というブランチ(条件分岐)→偽(false)ならなにもしない
  2. Speed=0ブランチが真(true)のとき→変数IdleTimeから変数CurrentDeltaTimeを引き算して0未満ならブランチに繋げる
  3. ブランチがtrueならIdleTime(待機モーション再生秒数)をリセット(6秒)し、Random Integer in Rangeノードを使って0~3の数値を選びIdle Numにセットする
  4. ブランチがfalseならゲットしたIdleTimeからCurrentDeltaTimeを減算した値をIdleTimeにセットする

以上が仕組みのすべてです。
なんかガイジンさんが海外フォーラムで同じことを遥かに難しいノードでやっていましたが、これくらいシンプルなノードできちんと動いています。
※IdleTimeを引き算ではなく足し算で算出しているので面倒なことになっていた。

さて、今回もサンプルプロジェクトへのリンクを貼っておきます。
内容は前回までと同じものですが、改良した「BlogStatueAnimBP2」を収録し、キャラクタBPで指定しています。

onedrive.live.com