BLOGブログ

2015.12.24UE4UE/ Blueprint

[UE4] Pure関数とNonPure関数

改訂バージョン: Unreal Engine 4.19

今回は、少し上級者向けのブループリントのお話です。

 

Pure関数とNonPure関数

ブループリント関数には、Pureというオプションがあります。
今回は便宜上、コレがONの関数をPure関数、OFFの関数をNonPure関数と呼びたいと思います。

gettestvalue

 

このオプションを変更すると、関数の呼び出し方法が下図のように変化します。

pure_vs_nonpure

左がPure関数、右がNonPure関数です。実行ピンの有無が変化します。

今回は、これらの挙動の違いを解説してみたいと思います。

 

呼び出しタイミング

まず、Pure関数とNonPure関数では呼び出されるタイミングが異なります。

実行ピンを持つNonPure関数は、単純に処理順がそのノードに到達した際に実行されます。

それに対して実行ピンを持たないPure関数は、何らかのNonPure関数が実行された際に、そこから戻り値を参照されていた場合に実行されます。
ココで注意すべきなのは、参照が発生する際に毎回実行される、ということです。

 

例えば次のような場合、全く同じ値を参照するにも関わらず、GetTestValue関数は100回呼び出されることになります。

pure_call

Pure関数の組み合わせで複雑な計算を行う場合や、Pure関数内で複雑な計算を行っている場合などは、注意した方が良いでしょう。

 

戻り値の保存

もうひとつ重要な違いが、NonPure関数の戻り値は、次に同じノードが実行されるまで保存される、ということです。

Pure関数は、戻り値が参照される度に関数が実行され、値が再評価されます。
しかし、NonPure関数はExecピンから処理が流れてきた場合のみ実行され、その際に戻り値が保存され、後から参照されても最後に実行された際の戻り値が再利用されるのです。

そのため、処理的には連続していなくても、下記のようなことが可能になります。

blog_nonpure_ret

ただ、この書き方はC++等に慣れたプログラマにはとても気持ちの悪いものに感じるかと思いますが…

 

NonPure関数の戻り値を利用した最適化

この、戻り値が保存される、という動作を利用すると、場合によってはブループリントの処理を最適化することが出来ます。

用途的にはPure関数なのだけれど内部で複雑な計算を行っていて、その計算結果は何度も繰り返し利用される、というようなケースがあったとします。

この関数をあえてNonPure関数として実装し、繰り返し利用する前に1回だけ呼び出しておくことで、わざわざローカル変数等を用意せずに計算結果を再利用することが出来ます。

nonpure_for_opt

上図の例では、最初と同様の結果ながら、GetTestValue関数の呼び出しは1回だけで済みます。

これが有効に働くケースはそれほど多くはないかもしれませんが、時には、あえてNonPureでGet関数を実装する、という選択肢もあることを知って頂ければと思います。