アンリアル日記

ゲームプログラマー2年目です。主に家庭用。

UMGでのキー入力イベントをC++で書く[UUserWidget::NativeOnKeyDown]

はじめに

UMGでは普通のブループリントで実装できるようなインプットキーイベントが受け取れません👇 f:id:taronoguchi:20200617195126p:plain

そこで、ウィジェットブループリント内でOnKeyDown関数(場合によってはOnPreviewKeyDown関数)をオーバーライドして実装することで、キー入力を受け取ることができるようになります。

これについては以下の方の記事を参考にしてください。

katze.hatenablog.jp

ただ、欲しい入力イベントを全部実装していたら結構ノードつなぐのしんどいですよね...

そこでこれらをC++で実装してしまい、それを継承したウィジェットブループリントを作ればかなり楽できそうですね。

それでは実際にやっていきます。

UUserWidget継承のC++クラス作成

UUserWidgetをベースにC++クラスを作成します。

f:id:taronoguchi:20200617200646p:plain

ここにOnKeyDown関数を実装すればよいのですが、なんと、C++ではOnKeyDown関数をoverrideできません。

エンジンソースのUserWidget.hをのぞいてみると... f:id:taronoguchi:20200617201211p:plain それもそのはず、BlueprintImplementableなだけでvirtualがついていません。 そしてもちろんC++では、virtualキーワードがない関数をoverrideできません

どうすればいいか。

UserWidget.hの1250行目あたりを見てみると... f:id:taronoguchi:20200617201633p:plain virtualついてるやついっぱいあるやん!!

プレフィックスNative-がある同様の関数がたくさんありますね! どうやらこれを使えば良さそうです。

ただこれを使うには[プロジェクト名].Build.csにて"Slate""SlateCore"モジュールを有効化してあげる必要があります。

SlateとSlateCoreの有効化

早速[プロジェクト名].Build.csに行って、有効化しましょう。

f:id:taronoguchi:20200617202340p:plain

👆これを、こう👇

f:id:taronoguchi:20200617202428p:plain

ここに関しては公式のドキュメントにも詳しく書かれています。

docs.unrealengine.com

UMGでもスレートの一部を使ってるからなんでしょうかね、スレートを有効にしないといけないっぽいです。

無事モジュールが有効化できたら先ほど作ったC++クラスに処理を書いていきます。

NativeOnKeyDownのoverride実装

まずはヘッダーでoverrideする関数の宣言と、特定のキーで呼び出す関数を作成します。 今回はWASDとTABだけにしておきます。

呼び出す処理はBlueprintで実装できるようBlueprintImplementableEventにしておくとよいかと思います。

f:id:taronoguchi:20200617210016p:plain

続いてcppファイルです。

Blueprint上でOnKeyDown関数を実装するのと同じようにやっていきます。

f:id:taronoguchi:20200617203737p:plain

ちなみにFReply::HandledFReply::Unhandled関数はstaticな関数なのでFReplyインスタンス化しなくても呼び出せます。

ではこれを継承したウィジェットブループリントを作って今実装したものを使ってみましょう。

Widget Blueprintの作成と実装

C++クラスを継承してウィジェットブループリントを作成します。

このとき、C++クラスを右クリックして"Create C++ class derived from..."を選択してしまうと普通のBPエディターが開いてしまうので、WidgetBlueprintを作ってから親を変えます。

f:id:taronoguchi:20200617204348p:plain

リペアレント👇

f:id:taronoguchi:20200617204433p:plain

リペアレント後は以下のように先ほどC++で宣言した関数を実装することができます。

f:id:taronoguchi:20200617204709p:plain

ではこのWidgetを表示してみましょう。

ちゃんと実行されていますね👇

f:id:taronoguchi:20200617204946p:plain

※ちなみに(Native)OnKeyDownを使うときは、対象のWidgetにフォーカスがなければいけないのと、InputModeUIOnly(またはUI and Game)が有効でなければならないので、そこを忘れずに。 f:id:taronoguchi:20200617205158p:plain