大福未来研究所

大福フューチャーラボのなんか色々なアレ。プログラミング(C++/DirectX/Unity/UE4あたりやりたい)とか音楽とかの。

【UE4】ウィジェットでメニュー画面などを作った際にマウス入力とキーボード/ジョイパッド入力を両立させる

ウィジェットブループリントあるある

UE4のウィジェットブループリント、とても便利に使ってます。
拙作「L.F.O.」のタイトル画面もポーズ画面も死んだときの画面もスコア表示等のUIも全部ウィジェットです。

しかしひとつだけ困ったことがありました……

「キーボード入力やジョイパッド入力のイベントがないやん!!!!」

そう、キーボードやジョイパッドでのインプットイベントに対応していなかったのです。



なので作ってみました。


間接的にインプットを取る

ウィジェットブループリントではキーインプットをイベントとしてグラフに作ることは出来ません。
しかし、アクタブループリントのキーインプットイベントからウィジェットブループリント内のイベントや関数を呼び出すことは出来ます。
例えるとこんな感じになります。

f:id:dfk_ohnuma:20170315221325p:plain

その手順を説明していきます。


インターフェースを作ろう

この方法で入力を取れるようにする場合、ウィジェット側に持たせておくブループリントインターフェースがあると便利になります。
というのも、ブループリントインターフェースは対象のオブジェクトを指定して呼び出す時、
そのオブジェクトのクラス名や実際にそのオブジェクトクラス内に該当するイベント及び関数が存在するかどうかに関係なく、
メッセージとして投げっぱなしジャーマンをしてくれるからです。

というわけで、さっそくブループリントインターフェースを作ってみましょう。今回は、

・カーソルを上移動させるCurUp
・同じく下移動させるCurDown
・決定ボタンを押すPushDecide

この3つのイベントをブループリントインターフェースで定義します。

f:id:dfk_ohnuma:20170316001315p:plain

あっという間に出来ました。
このブループリントインターフェースを、ウィジェットブループリントに実装します。
f:id:dfk_ohnuma:20170316001512p:plain
これで、このウィジェットブループリントの中に先ほどの3つのイベントが増えました。


使い捨てアクタくん

次に、入力用のアクタブループリントを作成します。今回の場合、中身はこのようになっています。

f:id:dfk_ohnuma:20170316005814p:plain

複数の種類のウィジェットに対応できるようにするため、変数のWidgetはObject型のリファレンスにしてあります。
また、この時、
f:id:dfk_ohnuma:20170316011004p:plain
「ポーズ中でもティックする」にはチェックを入れておかないと、ポーズ中に出て来るウィジェットなどに対して動作してくれなくなります。


この手段を使う場合、ウィジェット自身が入力用のアクタをスポーンし、そこに一対一の関係で紐付けをする必要があります。
そして、ウィジェットがビューポートからリムーブされる際、入力用のアクタも同時に破壊されるようにしなければなりません。

ウィジェット側のコンストラクタには、
f:id:dfk_ohnuma:20170316010438p:plain
このように入力用アクタをスポーンして、そこに自分自身のリファレンスを登録させるようにしています。
そして、スポーンした入力用アクタのリファレンスを変数にもっておきます。


あとは、(適当な作りではありますが)それぞれの入力に対応したイベントと、それに応じた動作をウィジェット側に組み込んでみましょう。
f:id:dfk_ohnuma:20170316010742p:plain
f:id:dfk_ohnuma:20170316010746p:plain
決定ボタンを押したときにはウィジェットが消えるので、入力用のアクタにも消えてもらいます。

これで、ウィジェットに対するマウスの入力の可否に関係なく、ウィジェットへのキーボード/ジョイパッドの入力が可能になります。

まとめ

ブループリントインターフェースと入力用アクタを使うことで、ウィジェット自身だけではやりづらい動作や実装も、
色々と組み込みやすくなると思います。
もし面白そうだと思ったら、是非試してみてください。
また、もっと効率のいい方法をご存知の方いらっしゃいましたら、是非教えてください。
ここまでお読み頂き、ありがとうございました。