iPX社員によるブログ

iPX社員が"社の動向"から"自身の知見や趣味"、"セミナーなどのおすすめ情報"に至るまで幅広い話題を投下していくブログ。社の雰囲気を感じ取っていただけたら幸いです。

UEPythonを使ってみた結果

前書き

はじめての方、はじめまして。久しぶりの方、お久しぶりです。高橋です。
今回はPythonコードをUEPythonへ書き換えているときに気づいたことをつらつらと書いていこうと思います。
UEPythonを使い、UE4の中でPurePursuitという経路追従アルゴリズム使い船を動かそうという記事にしようと思っていたのですが、書く時間がなかったので次回にします。
PurePursuitの参考記事はこちら
myenigma.hatenablog.com


UEPythonの環境構築に関しては以下のブログで触れられているので参照ください。
ipx.hatenablog.com

UEPythonの特徴

特徴1

UEPythonの特徴というよりもUE4の処理の特徴でもありますが、イベント駆動型の処理が付与されています。
f:id:ipx-writer:20190724101739p:plain
イベント駆動型の処理がどういったものかというと、「プログラムが動作中定義したイベントが行われた時、そのイベントの内部に記載された処理が呼び出される」といったイメージです。
具体例としては以下のようなイベントです。

  1. 「ゲームが始まった」時
  2. 「あるキーが押下された」時
  3. 「フレームが更新された」時
特徴2

もう一つの特徴として、UE4では処理が描画されるタイミングがフレーム単位となります。30FPS(1秒間に30回の描画)ですと、フレームが更新される0.033...秒ごとに処理の結果が表示されます。
それにより、各フレーム間で行う処理がすべて完了するまでUE4は描画せず待機することになります。フレーム間の処理が遅くなれば、一般に言う処理落ちという現象になります。
具体的に起こる現象を、whileループの処理を例に説明します。
i=0
while i < 10:
i += 1
描画関数('%s',i)
といったプログラムがある場合、普通のPythonではwhileが呼び出されるたびコンソール画面などに値が出力されますが。しかし、UE4ではwhileを処理している間待機状態になっており、すべての処理が完了した後フレームが更新されたタイミングで描画されます。
試しに以下のようなプログラムを実行してみます。
FPSは画面が更新される周期です。delta_timeはフレーム間の時間が保持されるので逆数を取るとFPSとなります。
f:id:ipx-writer:20190725124502p:plain
iの値を1000000と2000000でそれぞれ実行してみます。
・i = 1000000
f:id:ipx-writer:20190725124742p:plain
・i = 2000000
f:id:ipx-writer:20190725124852p:plain
whileループの処理が二倍になるとFPSがおおよそ半分になっていることがわかります。

whileループをフレーム処理へ

前述のようなことからpythonで書かれたwhileループ内でゴリゴリデータを更新していくようなプログラムはそのままUE4に乗せれません。
たとえばpython単体で船を移動させる関数(内部でwhileループ)があり、返り値を船の座標としてUE4に渡すようにするとします。実行するとゲーム開始後長いフリーズの後に船が開始地点からゴール地点まで瞬間移動します。
そこでUE4はフレームごとに更新されるので、フレームごとに処理を行うtickイベントにwhileループの中身を詰め込みます。そうすることでUE4の1フレームごとに処理を行うことができます。
上記のwhileループであれば以下のように書き換えます。
f:id:ipx-writer:20190725142653p:plain
結果 : 1フレームごとに処理が行われます。
f:id:ipx-writer:20190725143340p:plain
制御ロジックに触れたことがある方で、フィードバック制御や開ループなどそういった言葉を聞いたことがある方ならイメージが付きやすいかもしれません。

あとがき

whileがUEPythonで使えないみたいな書き方になってるかもしれませんがそういうわけではありません。処理と描画の関係を考えて組み替える必要がある場合があるということです。
次回は前書きに書いたようにpurepuresuitの実装を書いていけたらなと思います。