投稿

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ノード化する…

[UE4] UE4.16リリースノートピックアップ

イメージ
今回は、先日新しいバージョンが公開されたUE4.16の新機能をピックアップして紹介します。この記事は、ドキュメントのリリースノートにもとづいて作成しました。

ArrayGet(ref)ノードの追加 原文:New: 'Array Get' node. ・Can toggle between returning a reference or copy. ・Using a reference solves a longstanding issue with arrays of structs not being able to easily make changes to the items in the array.
図1左下部のような、配列要素のリファレンスを取得できるArrayGet(ref)ノードが追加されました。図1の例では、デフォルト値がfalseな要素を持つ構造体の配列に対して、ArrayGet(copy)とArray(ref)で配列要素を取得・変更した時、実際に配列内の要素が書き換わるか検証しています。ArrayGet(copy)では構造体のコピーが作成されるため、値を変更しても配列要素の値は変更されませんが、Array(ref)では構造体のリファレンスを変更しているため、配列要素の値が変更されます。
トグル ノード選択 原文:Updated marquee selection in graph editors. Ctrl dragging now inverts nodes' selection state, instead of only deselecting them (holding alt is now for pure deselection).
ノードが選択されているとき、Ctrlを押しながらマーキー選択をすると、範囲内にある選択済みノードは非選択ノードに、非選択ノードは選択済みノードにトグルされるようになりました。 Blueprint関数内での引数のGetノード化 原文:New: Function inputs are now exposed as variable "Get" nodes via the right-click context menu in a Blueprint func…

[UMG]インベントリシステムを作る

イメージ
この記事を読むと、UMGで図1のようなインベントリシステムが出来上がります。

はじめに インベントリシステムは多くのゲームで使われるシステムで、UE4でこれを実現する方法を調べると、既にたくさんの人が実装方法を紹介しています。特に役に立ったのは以下の2つのページです。 ビデオチュートリアルフォーラムでの議論 作り方としてはドラッグ&ドロップ関連の、既に用意された関数を少し実装することで、簡単に作ることができるようです。今回は、図1のような「要素の交換が可能」なインベントリシステムの実装方法を紹介します。 ドラッグ可能ウィジェットの作成 まずは、ドラッグ可能なウィジェットを作成します。図1における、カーソルで掴んで移動しているウィジェットの部分です。はじめに、UI_DraggableElementという名前のWidgetBlueprintを作り、図2のようなレイアウトにします。
SizeBoxを図2の赤い部分のように設定します。サイズは128*128で固定して、SizeBoxにマウスオーバーしたときにカーソルの見た目を手形にするために、CursorをHandにします。 SizeBoxの子ウィジェットにはNamedSlotを配置します。ここでのNamedSlotは、UI_DraggableElementの見た目をHUD上で変更するためのものです。
次に、図3のようにOnMouseButtonDownを実装します。
関数のオーバーライド一覧からOnMouseButtonDownを選んで関数を作成し、次に、その関数をDetectDragIfPressedノードを用いて図3のように実装にします。これで、UI_DraggableElement上でマウスの左ボタンが押されると、DetectDragが通知されるようになります。
次に、図4のようにOnDragDetectedを実装します。
こちらも同様に、オーバーライド一覧から作成します。関数はCreateDragDropOperationノードでDragDropOperationオブジェクトを作成し、それを返します。ここで作成したDragDropOperationは、ドラッグ&ドロップ関連の様々な関数が実行される際に、引数として渡され、その実装で自由に使用することが出来ます。
このノードの引数の意味は次のようになります。 Class…

[UE4]ベンチマーク結果に応じて描画品質を変える

イメージ
はじめに UE4の[Settings]->[Engine Scalability Settings]には、品質をまとめて設定するボタンがあります。特にAutoボタンは、品質を自動決定してくれる便利な機能です。

品質はランタイムで変更することができます。詳しくはalwei氏の記事が参考になります。基本的には、図2のようにGetGameUserSettingsノードでGameUserSettingsオブジェクトを取得して、Set~ノードで品質の各項目を設定し、ApplySettingsで設定を反映させます。

今回はその中でも、図1のAutoボタンに相当するRunHardwareBenchmark&ApplyHardwareBenchmarkResultsノードを紹介します。
ベンチマーク結果に応じて品質を変更
図3のようにノードを設定すると、Autoボタンに相当する結果が得られます。 各ノードについて説明します。 RunHardwareBenchmarkは、ベンチマークを行うノードです。ただし、これはSet~ノードと同じで、ノードを実行してもベンチマークが行われるだけで、その結果による最適な設定を反映しません。Set~ノードではApplySettingsノードを実行することで設定を反映するように、RunHardwareBenchmarkノードではApplyHardwareBenchmarkResultsノードを実行することで、ベンチマーク結果による最適な設定を反映します。 RunHardwareBenchmarkの引数は次のようになっています。 WorkScale:ベンチマーク試行回数CPU Multiplier & GPU Multiplier:ベンチマーク結果の倍率 WorkScaleはベンチマークの試行回数です。最終的なベンチマークの結果は、複数回行われるベンチマーク結果の総和をWorkScaleで割ることで得られる平均となります。WorkScaleが小さいほど試行回数が少なく、計算量は減りますが、結果の信頼性に関わるため、通常はこの値は変更しない方が良いかと思われます。 CPU MultiplierとGPU Multiplierはベンチマーク結果の倍率で、この値が高い程、高い品質(負荷 高)を維持しようとし、値が低いほど、低い品質(負荷 低)に抑…

[UBT]ビルドイベントで自動ローカルバックアップ環境を作る

イメージ
今回はUE4でビルドイベントを使う方法を紹介します。
はじめに UE4プロジェクトの構成プロパティは少し特殊で、UBT(UnrealBuildTool)を使う都合上なのか、図1のように、設定できるプロパティが隠蔽されています(実際にはUBTを通して設定している、ということだと思われます)。
ここで、図1の右側には「ビルドイベント」や「カスタムビルドステップ」というものが確認できます。これは文字通りビルド前や後に、任意のコマンドを実行できる機能です。何に使うべきかイマイチ思いつきませんが、かなり昔、実行ファイルに必要なdllのコピーに使った記憶があります。
図1の左側にはこの項目が存在せず、機能として利用できないように見えますが、調べてみると、使用する方法が提供されていることがわかりました。今回は、これをUE4上で使用してみます。 Pre/Post build step in UBT プロジェクト全てをコピーするビルド後イベントを追加するによって、自動でローカルバックアップを作成してくれる環境を整備してみます。 .uprojectを次のようにしました。 Moduleの[]の後ろにカンマを置き、"PostBuildSteps"以下を実装しただけ(17~22行目)です。
コマンドは、UE4のプロジェクトをDドライブのUE4Project_LocalBackupディレクトリに丸ごとコピーする、といったことをしています。
詳細を少しまとめます。
まずxcopyコマンドですが、これはファイルをディレクトリ構造ごとコピーするコマンドです。詳しくは、こちらを参照してください。これにプロジェクトのパスを指定することで、プロジェクト内の全てのファイルをディレクトリごとコピーしようというアイデアです。
次に、ソースとして指定している$(ProjectDir)ですが、これはプロジェクトのディレクトリへのパスを表すマクロ(もしくはPATH、環境変数? 正しい名称はわかりません……)です。このように書くと、実行時に$(ProjectDir)の部分がプロジェクトへの絶対パスに置き換わります。使用可能なマクロはUE4のソースコード上に書いてあります。
ターゲットには、DドライブのUE4Project_LocalBackupディレクトリを指定しました。このディレクトリはコマンド…

[UnrealC++]UE4における正規表現について

イメージ
今回はUE4で正規表現を使う方法について紹介します。
はじめに UE4で正規表現を使うには、FRegexMatcherFRegexPatternを使います。 これらのクラスの実装(ICURegex.cpp)を見てみると、unicode/regex.hをラップして実装していることが確認できます。上記のFRegexMatcherとFRegexPatternのドキュメントを見ても関数の詳細が書かれていませんが、ICURegex.cppの実装とここを見れば関数の詳細を調べることができます。 UE4で使用されている正規表現は、名前から明らかにICU正規表現です。ICU正規表現のドキュメントはここにありました。把握するのが億劫になりますが、よく使う量指定子やキャプチャなどの書き方は、他の正規表現と大きく変わるものではありません。適当に検索した正規表現の書き方入門にあるものを参考に書いても、問題なく動くはずです。 正規表現のパターンを作る 今回は、文章の中に埋め込まれた「イベントの番号」を取得する方法について考えます。 例えば、次のような文章があります。
「この文章は<event 23>正規表現のテスト<event 551>です。」
この文中から、<event 23>と<event 551>をマッチさせて、キャプチャによって23と551を取得する正規表現を考えます。次のようにしました(筆者は正規表現にそれほど詳しくないので、見苦しい書き方があった場合は指摘するか大目に見てください)。
"< *event *([0-9]+) *>"
「<」は埋め込みの開始文字です。 「 *」は、スペースの0回以上の繰り返しにマッチします。「<event~」や「< event~」や「<      event~」のように、<とeventの間の任意の空白に対応するようしました。 「event」は埋め込みの識別文字です。 「 *」は前述と同じです。「~event21~」や「~event 345~」や「~event       8~」のようにeventと数字の間の任意の空白に対応するようにしました。 「([0-9]+)」は、1回以上の数字の繰り返しにマッチします。()は、キャプチャのために記述してい…

[UMG]マウス入力を阻害する-後編-

イメージ
今回は、前回の続きです。
前回は、Visibleなウィジェットを配置すると、それより後ろにあるウィジェットはカーソルとインタラクティブできないという内容について紹介しました。

実は、前回紹介した内容では、カーソルとのインタラクティブを完全に阻害できない例外があります。それが、アクターがクリックされたことを検出する「ActorOnClicked」イベントです。

ActorOnClicked イベントの作り方 はじめに、ActorOnClickedイベントでクリック入力を受け取るところまで紹介します。 まず、図1のように、PlayerControllerの「EnableClickEvents」を有効にします。
次に、クリックしたいアクターのコリジョンを確認します。コリジョンが有効でないと、ActorOnClickedは発生しません。図2はデフォルトのままですが、NoCollisionになっていなければ、とりあえず大丈夫かと思います。
最後に、図3のようにイベントグラフ上にActorOnClickedノードを追加すれば、アクターをクリックした時の処理を追加できるようになりました。このアクターをクリックすると、Helloと画面に出力されるようになります。
さて、これでアクターがクリック入力を受け取れるようになりましたが、これは前回のUMGによる手法では阻害できず、ActorOnClickedが実行されてしまいます。 今回に限っては、Branchで処理をはじく、Collisionを無効化する、EnableClickEventsをFalseにする等の方法が考えられます。ですが、それらの方法ではなくUMGによって阻害する方法を紹介します。
Buttonによって入力を阻害する 前回のSpacerのように、マウス入力を阻害するウィジェットとしてButtonを配置します。今回はどんなウィジェットでも良いわけではなく、Buttonでなければなりません。また、図4の右端のように、Buttonの前面をVisibleなウィジェット(図4ではBackgroundBlur)で覆うようなレイアウトは駄目です。
このままではButtonが見えてしまっているので、Spacerなどと同様に不可視にするため、Buttonの見た目を変更します。図5のように、次の項目を設定します。 画面全体に広げる(設定は親パ…

[UMG]ディゾルブエフェクトもできる、RetainerBoxについて

イメージ
RetainerBoxについて紹介します。これを使うと、例えば図1のようなUMG用ディゾルブエフェクトを作成することも可能です。

RetainerBoxとは Optimization(最適化)に分類されるウィジェットです。Retainer Boxの子ウィジェットの内容を、テクスチャ(RenderTarget)に指定間隔でオフスクリーンレンダリング(OSRと略します)し、その結果のテクスチャをスクリーンに描画するウィジェットです。OSRは毎フレーム行われるわけではなく、OSRが行われないフレームの間は最後にOSRされたテクスチャを再利用することでスクリーンへの描画負荷を減らします。 子ウィジェットの内容が複雑なものである場合、OSRの頻度が少ないほど描画パフォーマンスが向上する可能性があります。ただし、OSRの頻度を「毎フレーム」に設定したりすると、OSRされたテクスチャをスクリーンに描画する「二度手間」がある分、逆にパフォーマンスは悪化すると考えられます。今回は最適化の話に焦点を合わせませんが、使うときはパフォーマンスに留意する必要があると思われます。
今回は、Retainer Boxを用いたエフェクトを主に紹介します。実は、Retainer BoxはOSRされたテクスチャをスクリーンに描画する際、マテリアルによって描画内容を変えることが可能です。これはBorderやImageウィジェットのBrushにエフェクト用マテリアルを適用するのとは異なり、Retainer Boxにエフェクト用マテリアルを適用すると、子ウィジェット全てに対してエフェクトが適用されるのと同じ表現ができます。

Retainer Boxを使ってみる 前準備として、図2のようなUser Widgetを作成します。今回は、これをRetainer Boxの子ウィジェットにして全体にエフェクトを適用します。

まず、図2のウィジェットをRetainer Boxでラップして、図3のようにします。余談ですが、ウィジェットをラップするときはコピー&ペーストで作るより、Wrap With...の中から親としたいパネルウィジェットを選ぶ方が簡単です。

次に、Retainer BoxのEffect Materialにマテリアルを設定します。ここではCreate Materialを選んで、新しいマテリアル(アセット名は…