投稿

6月, 2017の投稿を表示しています

[UE4]UE4でPhysX Visual Debuggerを使う

イメージ
UE4の物理ライブラリにはPhysXが用いられています。PhysXにはPhysXのSceneをフレーム単位で記録・再現できるPhysX Visual Debugger(PVDと略します)と呼ばれるツールがあり、今回はこれをUE4で使う方法について紹介します。
PhysX Visual Debuggerの導入 まず、PVDをインストールする必要があります。図1のように、ダウンロードセンターのリストの中からPVDを探し、プラットフォームを選んでダウンロードします。ダウンロードするときは、NVIDIA Developer Programに登録する必要があることに注意してください。
PhysX Visual DebuggerとUE4を連携させる UE4と連携する前に、少しだけ準備(座標系の設定)が必要です。PVDを起動し、図2のようにPVDの右下にあるUp AxisをZ+に、ChiralityをLeft-Handedに変更します。この設定は起動する度に初期化されるので、起動の度に毎回行う必要があります。
次に、UE4をPVDに接続します。UE4をPVDに接続するには、コンソールコマンドで「pvd connect」を実行します(余談ですが、UE4とPVDの接続を切断するには、「pvd disconnect」を実行します)。今回はレベル開始後に即実行してほしいので、Execute Console Commandを使います。レベルブループリントで図3のようにノードを繋ぎました。
最後に、物理アクターの配置をします。図4のように適当なアクターをレベル上に配置し、MobilityをMovableにし、Simulate Physicsのチェックを有効にします。このようにしてゲームを実行すると、重力によって物理アクターが落下し、他の物理アクターと衝突しながら床を転がる様子が確認できるかと思います。
ゲームを実行後、起動しておいたPVDを確認すると、図5のように、UE4で作ったレベルに相当するPhysXのSceneがPVD上に再現されています。これで、UE4とPVDを連携させることができました。
PhysX Visual Debuggerの使い方  PVDの基本的な使い方を紹介します。詳細な使い方は、メニューバーにある[Help][Manual]から参照することができます。
PVDのカ…

[UBT]Target.csとBuild.csをUE4.16へ移行させる

はじめに UE4.16でTarget.csとBuild.csの記述方法が変更されました。4.16より前のコードプロジェクトをバージョンアップする場合は、変更箇所を修正する必要があります。具体的な変更箇所を確認する方法としては、以下が参考になります。
ビルド時のエラーログを参照するリリースノートを確認する4.15と4.16のコードプロジェクトを作成し、両者を比較する 今回は、3の方法で変更点をまとめます。

Target.csの変更点 まず、Target.csの変更点です。Target.csはデフォルトでGameとEditorの2タイプが生成されますが、生成直後の2つに違いはほとんどないので、今回はGameタイプのみを扱います。Target.csについてのドキュメントはここにありました。 まず、UE4.15でのTarget.cs(以降、415T.csと略します)は以下のようになっています。

次に、UE4.16でのTarget.cs(以降、416T.csと略します)は以下のようになっています。

コードがかなり違うことが確認できると思います。1つずつ変更点を確認します。
コンストラクタで基底クラスのコンストラクタが呼び出されるように変更 415T.csと416T.csの8行目を注目してください。416T.csでは、コンストラクタの後ろにbase(Target)が追加され、基底クラスのコンストラクタが呼び出されるように変更されました。 SetupBinariesの廃止 415T.csの17行目以降にあるSetupBinaries関数は廃止され、ここで行っていた処理は、コンストラクタで行われるように変更されました。 プロパティの移行 SetupBinariesで参照渡しされていた引数OutBuildBinaryConfigurationsとOutExtraModuleNamesは、接頭辞のOutを取り除いたプロパティBuildBinaryConfigurationsとExtraModuleNamesに変更されました。415T.csの23行目と416T.csの12行目がそれぞれ対応すると考えると理解しやすいです。

Build.csの変更点 次に、Build.csの変更点です。Build.csについてのドキュメントはここにありました。 まず、UE4.15でのBuild.cs(以降…

[UnrealC++]任意のイベントをLatentノード化する

イメージ
前回、Latentノードの作成方法と単純な実装モデルについて紹介しました。
今回は、前回の問題点を改善した実用的なLatentノード実装モデルを紹介します。具体的には、図1のような、特定のシグネチャを持つイベントをLatentノード化する(イベントが終了するまで待機する)WaitUntilFinishedの実装・使用方法について紹介します。

WaitUntilFinishedノードの作り方と使用方法のみを知りたい方は、「WaitUntilFinished Latentノードを使用する」項以降を参照してください。
イベント終了通知オブジェクトを作る 前回は、Latentノード化したイベントが実行しているかどうかはBoolean変数によって管理していました。しかし、Boolean変数で管理する場合はUPROPERTYをつけたメンバ変数を新たに宣言する必要があるため、Latentノード化したいイベントを追加する度に変数が増えてしまうという問題がありました。
そこでLatentノードが呼ばれる度に、終了を通知する機能を持つオブジェクトを動的に生成することで、過剰な変数宣言を防ぎます。最も単純なアイデアはnew演算子で動的にBoolean変数を割り当てる方法が考えられますが、これはBlueprintで対応できないため避けます。次のアイデアとしては、UObject継承クラスをNewObjectで生成する方法が考えられますが、これもGCの対応が面倒なので避けます。
様々なアイデアを試した結果、より良い結果を得られたのはAActor継承クラスをレベルにSpawnする方法です。この方法であれば、Blueprintとの相性もよく、DestoryActorによって明示的に破棄できるためGCの問題もありません。
LatentWaiter.hを次のように実装しました。

LatentWaiter.cppを次のように実装しました。

ALatenterActorクラスは、そのインスタンスがレベルに存在する(DestroyActorが呼び出されていない、またIsValidがTrueになる)とき、イベントが継続していることを示し、レベルから破棄されたとき、イベントが終了していることを示すものとします。すなわち、このアクターをDestroyActor(もしくはDestroy)することによってレベルから破…

[UnrealC++]Latentノードの作り方

イメージ
今回は、Latentノードの作り方を紹介します。

Latentノードとは? Latentノードとは、図1のような、ノードの右上に時計のアイコンが付いているものを指します。基本的にこれらのノードは「処理が終了するまでの間、後続の処理の実行を待機する」という動作を1ノードで実現するためのもので、処理の可読性向上に役立ちます。 本記事では、処理の完了に時間がかかるユーザー定義の処理を、Latentノードとして1つにまとめることを目標とします。
Latentノードを作る前に※本項はLatentノードの作り方とは関係のない話なので、手っ取り早く実装法が知りたい方は、次の項を読んで下さい。 Latentノードは処理の可読性を上げますが、一方で何でもかんでもLatentノードにすればよいというものでもありません。Latentノードを使いすぎると、どこで処理が止まっているのか・いつ処理が再開されるかといった把握が難しくなりますし、そもそも大前提としてC++が必要なためBP Onlyほど気軽には作れません。 そこで個人的に有用と考えている、BP Onlyで実現できるLatentモデルの代替を紹介します。
図2は、Heavy Eventが終了するまでPrint Stringの実行を待機するという疑似的なLatentノードの処理を行っています。「Latentモデル」とコメントされている部分が、Heavy Eventを擬似Latentノードにするための実装です。 これを見てわかるように、Heavy EventのLatentノードを作ったとしても、節約できるノードはコメント部の数ノードだけです。よって、Latentノードを作るときは、作る労力がこの代替に見合うかを考える必要があります。 とはいえ、実際にはLatentノードを作る度に待機フラグ変数を追加し、Branch-Delayで待機モデルを作るのはスマートではありません。なにより、Heavy Eventは後続の処理が待機される前提の実装をするのに、それが図1のアイコンのような形で明示されないのは非常に気持ちが悪いです。
Latentノードの作り方 次の2ステップで実装します。 FPendingLatentActionを継承して、Latentノードが終了したかどうかを監視するためのクラスを定義するUFUNCTIONにLatentノード化する…