Let's Enjoy Unreal Engine

Unreal Engineを使って遊んでみましょう

UE4 Math Expression(数学式)ノードを使いこなそう

UE4にはブループリントが実装されている当初から用意されているMath Expression(通称 数学式)という機能があります。最初はプラグインでしたが現在はエンジン自体の組み込み機能です。

これがMath Expressionノードです。
f:id:alwei:20210525201216p:plain

このMath Expression、最初からついている組み込み機能なのにその存在を知らない人を今でもよく見掛けます。そしてプログラマーでより経験の長い人ほどブループリントで四則演算を計算することを毛嫌いする人が多い気がしますが、そういう人のためにあるのがこのMath Expressionノードです。

公式ドキュメントは以下にあります。
docs.unrealengine.com

たしかに基本的な使い方は上記ドキュメントの通りなのですが、微妙にわからない点もいくつかあります。

Math Expressionで使えるノードについて、ヒストリアさんの以下の記事でも検証されているので引用しておきます。

historia.co.jp

  1. static 関数である
  2. BlueprintPure である
  3. ネイティブ関数である
  4. 出力が1つ(ReturnValue)だけある

これらを守っていれば比較的自由に計算式を構築できるということがわかります。ただし記事内でも触れられていますが、前括弧 "(" がDisplayNameに入っているノードは仕様なのか現在も使えないようです。

それではもう少し詳しく見ていきましょう。

既存ノードをMath Expressionに変換していく

Math Expressionに既存のノードを実際に変換してみましょう。今回は以下のような少しだけ複雑になってしまっているノードを変換してみます。ノードはTwitter上で ジースP さんが作っていたものを一部切り取ってみたものです。

f:id:alwei:20210525213908p:plain

この計算は全てMath Expressionに変換可能です。少しずつ変換してみましょう。まずは左上部分から変換してみます。

f:id:alwei:20210525214243p:plain

GetForwardVectorはRotote型の引数が必要なため、Rotate型を略式となるエイリアス名、"rot(0,0,0)"で定義しています。最後に変数Radiusと乗算をしたいのでそのまま入力するだけで変数Radiusを認識してくれます。

次はその下部分を変換してみます。

f:id:alwei:20210525214649p:plain

再びMakeRotatorの部分をエイリアス名で定義し、変数Yawと-1.0の乗算を行いたいので、(Yaw * -1.0)と記述しようとするとエラーがでてしまいます。Math Expressionでは現在式の中にマイナスを直接記述できない仕様?かバグ?かわからないところがあり、ここは引数として"Minus"を定義することで回避が可能です。そもそもfloatの正負反転するようなノードがあればいいのですが、ないものは仕方ないのでこのようになります。

次はその右側のノードを変換します。

f:id:alwei:20210525215419p:plain

RotateVectorを-1.0で反転するようにNegateVectorに入れるように式を組み立てます。ただし、ここでもエラーが出ています。原因はAとBという引数の型がfloatになっているためです。こちらはMath Expressionの詳細からAとBの型をVectorとRotatorに変更してあげることで解決します。

f:id:alwei:20210525215653p:plain

うまくいったので次にいきましょう。次は右下に繋がるRotationFromXVctorからの流れを変換します。少し複雑なので2段階で変換します。

f:id:alwei:20210525215946p:plain

RotationFromXVectorはVectorを引数にとるため、そのまま作るとエラーになってしまうため、先程と同じように詳細からfloatをVectorに変更することでエラーがなくなります。

f:id:alwei:20210525220408p:plain

更にRotatorFromAxisAndAngleを変換し、引数AxisとPitchに対して乗算していたのでそれも含めるようにします。(乗算は意味がない気がしますが)

f:id:alwei:20210525220626p:plain

最後はRotateVectorを変換します。これは既に変換しているので特に迷うようなところはありませんね。戻りのVectorは構造体ピンの分割を行っているだけなので、戻り値ピンを右クリックしてから構造体ピンの分割を選択することで、同様のピン数になります。

f:id:alwei:20210525220848p:plain

最終的にはこれくらいシンプルな見た目となり、非常にスッキリとしたことがわかります。

複雑な条件も書きやすい

Math Expressionはただ計算式を記載するだけではなく、論理演算の結果を返すこともできます。

f:id:alwei:20210525221739p:plain

例えば上記は全く同じ結果を返しますが、Math Expressionを使わない方は縦のスペースも含めてかなりとってしまうことになります。また間にNOTが入ってくると更にややこしくなってきてしまいます。

f:id:alwei:20210525223043p:plain

Math Expressionでは !演算子が使えないため、引数にNOTをもたせて比較したものを利用することで同様の条件を記述することが可能です。ノードの場合はどんどん肥大化して見づらくなってしまいますが、Math Expressionはまだ見れる量です。(そもそもこんな条件式を書きたくありませんが)
※ 完全に間違いです。これでは同条件にはなりません。代わりに以下の方法を用います

f:id:alwei:20210525231504p:plain

Math Expressionでは !演算子が使えないため、代わりに^演算子で代用が可能です。XOR演算で論理演算の反転が可能なため、TRUEとの比較でNOTと同じ結果になるはずです。

と、いうように上手く使うことでかなり複雑な計算や条件もMath Expressionで記述可能ということがわかったと思います。

ちなみに複雑な計算もそのままノードで書くより、Math Expressionで書いた方が最終的に最適化されるため、BPだけで最速を目指すのであれば積極的にMath Expressionを使った方が処理速度は上がることになります。

最適化されるというのは こちら でも語られておりますので、気になる方はどうぞ。

www.slideshare.net