[UnrealC++]SWindowで対話可能な外部ウィンドウを作る
図1 対話可能な外部ウィンドウ(左下) |
はじめに
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++部分の実装は終了です。
BlueprintでBP_MyGameInstanceを実装する
まず、図2のように、先程作ったMyGameInstanceを継承したBlueprintクラス(BP_MyGameInstanceとします)を作成します。
図2 MyGameInstanceを継承したBPクラスを作成する |
図3 GameInstanceClassを設定する |
図4 OnClickedを実装する |
最後に、レベルブループリントでマウスカーソルが見えるように変更します。図5のように実装します。
図5 レベルブループリントを実装する |
ここまで実装した後、ゲームを実行すると、即座に外部ウィンドウが立ち上がります。そして、ウィンドウ内にあるボタンをクリックすると、図6のようにゲームウィンドウ側にHelloという文字が出力されます。これで対話可能な外部ウィンドウを作ることができました。
図6 ボタンをクリックするとHelloが出力される |
おわりに
以前はWPFアプリケーションを作り、それとTCP通信するという方法で外部ウィンドウと対話する方法を考えたのですが、これは回りくどく、あまり良いものではありませんでした。今回の方法は、最近、Slateまわりを学習していたために閃いたアイデアでしたが、思いの外上手くいく結果となりました(Escでウィンドウを閉じるとクラッシュしますが……)。今回はSButtonを配置しただけでしたが、他のSWidget(ただしRutimeのものに限る)に対しても同様の方法が取れると思うので、これを応用すれば複雑なGUIも構築できると思います。この方法が何かの参考になれば幸いです。この記事は次のバージョンで作成されました。
Unreal Editor(4.16.2-3514769+++UE4+Release-4.16)
Microsoft Visual Studio Community 2017 Version 15.1 (26403.7)
コメント
コメントを投稿