投稿

[UnrealC++]SWindowで対話可能な外部ウィンドウを作る

イメージ
はじめに UE4を非ゲーム的な用途のアプリケーションを作成する時、一般的なアプリケーションのようなGUIを作りづらいという問題に直面したことがあります。UMGで作るのが最も簡単ですが、外部ウィンドウにGUI部分をまとめて、ウィンドウ同士で対話するというやり方もあります。
今回は、図1のような、「ボタンを持ったウィンドウ」を生成し、ボタンが押されると特定の処理が実行されるような、対話可能な外部ウィンドウの作り方を紹介します。

実装 C++でMyGameInstanceを実装する Slateを用いるので、今回もSlateモジュールを追加します。.Build.csを次のようにします。
次に、GameInstanceを継承したクラス(名前をMyGameInstanceとします)を作成します。GameInstanceを選ぶ理由ですが、GUIをまとめたウィンドウ(以降、GUIウィンドウと略します)はレベルに依存せず、起動から終了までどこからでもアクセスできる必要があり、そのような機能に最も適当と考えたからです。
.hを次のように実装します。
OnClickedはGUI ウィンドウ上のボタンを押されたときの関数です。Blueprintで継承して、BP上で実装します。
.cppを次のように実装します。
GameInstanceのInit関数をオーバーライドして実装しました。
関数の本体は、SetTimerForNextTickを使って実行を遅延させます。これは、Init関数が呼び出される時点でゲームのウィンドウがまだ完全に生成されていない問題を回避するためです。
次に、SNewによってSWindowを生成します。SWindowのコンテンツには、SButtonを与えます。SButtonのOnClicked_Lambdaには、BlueprintImplementableEventに指定したOnClicked関数を呼び出すようなラムダ式を与えます。
最後に、FSlateApplication::Get().AddWindowAsNativeChildに、GUIウィンドウであるwindowと、ゲームウィンドウである GetGameViewportClient()->GetWindow()を親ウィンドウとして与え、ウィンドウ同士を関連付けます。
これで、C++部分の実装は終了です。

[UMG]NativeWidgetHostを継承してカラーピッカーを作る

イメージ
今回は、NativeWidgetHostというウィジェットを使って、動画のようなカラーピッカーをUMG上で使えるようにする方法を紹介します。

はじめに SWidgetとUWidget UE4エディタは多数のUIコンポーネント(ラベル、テキストブロック、ボタン、あるいはそれらを組み合わせたもの)で構築されており、それらUIコンポーネント全てがSWidget(を継承したクラス)です。図1はWidget Reflectorというツールを用いて、エディタを構築するウィジェットを調べたものです。WidgetName一覧にある接頭辞にSがついたクラスは全てSWidgetを継承したクラスであり、UE4エディタがSWidgetを継承したクラスの組み合わせによって構成されていることがわかるかと思います。
一方で、図2はUMGのパレットを示したもので、この一覧にあるウィジェットがUWidgetです。UMGを使っていて気づいた方もいらっしゃるかもしれませんが、図2にあるウィジェット、例えばComboBoxやCheckBoxといったウィジェットのデフォルトの外観は、UE4エディタにある同じ機能を持ったウィジェットとまったく同じものです。それもそのはず、UWidgetはSWidgetをUMG向けにラップしたクラスであり、UWidget内部で使われているSWidgetと、UE4エディタで使われているSWidgetは同じものであるためです。
NativeWidgetHostとはUE4のドキュメントには、このように書かれています。 「子スレート ウィジェットを 1 つ格納できるコンテナ ウィジェットです。UMG ウィジェット内部にネイティブ ウィジェットをネスティングすることだけが必要な場合に使用します。」 ここで「子スレートウィジェット」とは、SWidgetを継承したクラスのことを指し、UWidgetとして公開されていないSWidgetをUMG上で使いたい場合に用いる、と説明されています。実は、SWidgetをゲーム中に使うこと自体は、UMGを仲介する必要がありません(参考)。しかし、この方法ではUIデザインはまともにできないため、より扱いやすくするためにUMGに公開する必要があります。そのようなとき、UMGに公開する方法の1つとして、NativeWidgetHostが用意されています。 先程「…

[UE4] Blueprintのグラフを画像として出力するプラグイン GraphShutter の配布・導入・使用法について

イメージ
はじめに UE4でBlueprintを他の人と共有するとき、皆さんはどうしていますか。言葉で説明する、プロジェクトで配布する、BlueprintUE.comを使うなど方法は色々ありますが、やはりスクリーンショットを使うことが多いかと思います。
スクリーンショットを使う利点としては、UE4上でのノードの表示内容を視覚的に届けられる点が挙げられます。一方でノードの量が多いと、それを収めようとグラフ全体をズームアウトしてしまい、結果的にノードの名前も読み取れないぐらいまで縮小されてしまうことがあります。私は、これを避けるためにグラフのスケーリングを変えず、部分的にスクリーンショットを撮って、画像編集ソフトで結合するという方法をとっていました。これは手軽さからは程遠い作業で、いつも簡易化できないか考えていました。
今回は、それらの問題を解決するために、「任意のグラフを画像として出力する」プラグインを開発しました。このプラグインを使えば、どれほどノードが多くても、ショートカット1つで、グラフを見やすい大きさの画像として出力することができ、画像編集の手間を省くことができます。

注意事項 本プラグインは現在開発が始まったばかりで、多くのバグと問題を抱えています。また、この記事を書いている段階では、「グラフを画像として出力する」ということが実現可能であることを実証するための最低限の機能しか実装されていません。そのため、動作が非常に不安定であり、本番環境での使用を推奨しません。また、このプラグインを用いて発生した損害等に対する責任を製作者は一切負いません。

配布 次のリンクから、プラグインのバイナリをダウンロードできるようにしました。
https://1drv.ms/u/s!AqklsC13CiMggaMKGgdDT4C8p0wUHA

導入 1. ダウンロードしたzipファイルを解凍します。
2. プラグインを使用したいプロジェクト内に「Plugins」フォルダを作成します。

3. Pluginsフォルダの中に解凍したGraphShutterフォルダをコピーします。

4. UE4を起動してメニューの[Edit][Plugins]からPlugin Managerを起動し、Otherカテゴリ内にあるGraphShutterプラグインがEnabledになっていれば導入は完了です。

使用法…

[UnrealC++]LandscapeのHeightmapをC++から変更する

イメージ
今回は、図1のような、Landscapeの高さをC++コードによって変更する方法について紹介します。

はじめに 本記事はUnreal Engine 4 Scripting with C++に記載されていた、LandscapeのHeighmapを変更する方法を参考にしています。
個人的には、Landscapeをランタイムで生成するようなものを期待していたのですが、これは上手くいきませんでした。Editorモジュールも使っており、現状、ゲーム制作で使えるレベルではありません。それでも、Landscape関連のAPIを扱う際の取っ掛かりになるかもしれないので、方法をまとめておきます。

実装する Build.csにモジュールを追加する Landscape、LandscapeEditorモジュールをPrivateDependencyModuleNamesに追加しました。LandscapeEditorモジュールはEditorモジュールなので、Gameモジュールに追加するのは不適切なのですが、今回は簡略化のためにGameモジュールに追加しました。

GenerateLandscape関数を作成する BlueprintFunctionLibraryで作成します。まず、.hを次のようにしました。
次に、.cppを次のようにしました。
順にコードについて説明します。
(11~15行目)レベルにあるLandscapeActorを取得しています。TActorIteratorによって列挙していますが、有効なものが1つ見つかれば、それだけをHeightmapの変更対象とします。特定のLandscapeを変更対象としたいときは、ActorTag等を使うべきかもしれません。(18行目)レベル内全てのLandscapeInfo(コンポーネントサイズやサブセクションサイズなどの情報を管理するオブジェクト)をリセットし、再生成する関数のようです。Unreal Engine 4 Scripting with C++に必要と書いてあるのですが、必要性がイマイチ分かりませんし、今回に限っては無くても動作しました。一応記述しておきました。(21~23行目)対象のLandscapeの大きさを取得しています。これはLandscapeのOverall Resolutionと一致します。これを用いてHeighmapのデー…

[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)することによってレベルから破…