Let's Enjoy Unreal Engine

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

UE4 ブループリントでコルーチン的な事をやってみる

コルーチンというのはなかなか専門的な用語で、プログラマー以外の方はきっと聞いた事もないでしょう。プログラミング言語として、コルーチンが使えるものはC#Luaが有名です。

コルーチン - Wikipedia

コルーチンとは、一旦処理を中断した後、中断した場所から処理を再開できます。つまり、これは擬似的な並列化を行なう事が出来ます。なのでよくマルチスレッドの代わりとして用いられますが、コルーチンの場合はもっと小さい単位で細かい事を処理させるのに向いています。

これを実現させるために、とあるノードがあります。わかる人にはすぐわかるでしょう。

f:id:alwei:20150424115239p:plain

そう、Delayノードです。

 Delayノードとは?

Delayノードとは、Latentノードの一種です。まずLatentノードというものがよくわからない人がいると思うので少しだけ解説します。

Latentノードはその場で処理を行なわずに、一時的に処理をブロックしてその場で処理を中断させます。Latentとは日本語で潜在的な、という意味になり、その名前の通り裏で隠れて処理を行ないます。

Delayノードの場合は、裏で処理を行なうというよりは裏で何も処理をしていないのですが、内部でタイマーをカウントし、それがゼロになった時にイベントを発行し、その後の継続処理を行ないます。

f:id:alwei:20150424120103p:plain

これは3秒間待ってから、処理を継続させて続きを処理させています。

ではコルーチンってどうやるの?

なんとなく、UnityでC#を使ったコルーチンを書いた事がある人ならばわかると思います。Unity C#の場合では " yield return new WaitForSeconds(秒数) ; " というような書き方で実現できます。

そして、" yield return null; "と書くとコルーチンはそのフレームの処理を終了して次のフレームで再開します。これはDelayノードでも実現可能です。

f:id:alwei:20150424120655p:plain

DelayノードのDurationに"0"と指定すれば、そのフレームの処理を終了し、次のフレームで処理を再開します。これは上記の" yield return null; "と同様の挙動です。この時点でコルーチンのような事が出来るというのがわかります。

ではこれを応用してみます。

f:id:alwei:20150424121242p:plain

Begin Playを実行後に、Flagがオンになるまで、処理をまわし続けます。ここではMultiGateを使って6回目にFlagがオンになるようにしました。そしてDelayで0秒待ち続けて、Branchに再度繋ぎます。

その間、Tickをまわし続けているので、処理がブロックされずに動いているのかが確認出来ます。ではこれを実行すると…

f:id:alwei:20150424121621p:plain

少し読みにくいですが、処理は下から古いもので上になるほど新しい処理です。つまり、5回目まではハズレで、その間にTickも動いている事がわかります。そして6回目にアタリになり、処理が終了できました。

これらは全てBegin Playの流れの中ですが、処理がブロックされずに並列に処理された証です。つまりコルーチンが実現出来ているという事です!

これは非常に強力な機能であり、ブループリントはイベントグラフ内であればどこでもこの処理が書けます。※マクロの中でも書ける

更に応用した考え方

エネミーのAIを作成するとしましょう。

f:id:alwei:20150424123129p:plain

あまりにも適当な絵ですが、イメージとしてはこんな感じです。これらのフローを作成する時に、次のステートへ移行するまではフローを完全にブロックし、完了次第、次のフローへ移行するという事が簡単に作成する事が出来ます。

コルーチンはこういう順番に順番処理させるという事が得意という事です。よく考えて使えば使うほどその効果の高さを実感出来ると思います。

ちなみにコルーチンは処理が並列に実行されているように見えて、実は完全に並列に実行されているわけではないので、処理並列化による高速化は行なえません。それはブループリントとDelayノードでも同様です。

しかしとても便利な仕組みである事に代わりはありませんので、上手く使っていきましょう。