BLOGブログ

2018.02.16UE4/UMG

[UE4]UMGのNavigation機能を使ってみる

今回はUMGのNavigation機能について解説していきます。
この機能を使うと入力処理を書かずにキーボード・ゲームパッド操作に対応できます。
クリック操作も生きるのでPC向けのゲームのように複数の操作に対応できます。

手順

①Widgetを配置
※今回はButtonWidgetを使用します。

②IsFocusableにチェックが入っていることを確認

③初期カーソルが合うボタンをSetKeyboardFocusで設定

※Constructイベントではうまくフォーカスしないので表示するイベントを作って呼ぶようにして下さい。

④UIの入力設定
Navigationの項目で上下左右・前後を設定します。
上下左右はキーボードの上下左右、ゲームパッドのアナログスティック、上下左右キー
前後はTabとShift+Tabでの操作になります。
とりあえずはEscapeでOKです。

⑤フォーカスがわかる点線の表示・非表示設定
プロジェクトの設定→User Interface→Focus→RenderFocusRuleを変更

Always         常に表示
Non Pointer  マウスカーソルが別なWidgetをクリックした場合消えます。
Navigation    Only Widgetにフォーカスが移動した時表示
Never           常に非表示

⑥Widgetを作成し入力を受け付けるようにします。

ゲーム中の入力を無効にしたい場合は「SetInputModeUIOnly」
ゲーム中の入力をそのまま有効にしてUIを操作したい場合は「SetInputModeGameAndUI」を設定して下さい。

クリックイベントにも対応
一部のWidgetはクリックイベント(OnClicked)に対応しています。(ボタン、チェックボックス等)
スペースバーとエンターキー、コントローラーのAボタン(EKeys::Gamepad_FaceButton_Bottom)でボタンをクリックできます。
注意する点としては、独自に作ったWidgetではクリックイベントは対応してません。
OnKeyDownをオーバーライドして 独自で実装する必要があります。

うまくいかないときチェックするべき点
・collisionの設定
Visibleになっているか確認してください。
コリジョンが有効になっていないとフォーカスされません。
逆にフォーカスさせたくない場合はコリジョンを無効にして下さい。

・配置
XY方向に重なっていないと次のWidgetを探す事ができませんので注意して下さい。
もしレイアウト的に特殊なことをしたい場合は、Navigationの設定でExplictで移動先のWidget名を指定することで、
次の移動先を指定することができます。

 

ほかにTips的なことを…

全然関係ない部分をクリックした場合フォーカスが外れてしまう

これは何らかのアプリ側の仕様をきめて独自に実装する必要があります。

例として…
TickですべてのボタンのHasKeyboardFocusを確認してすべてのフォーカス外れていることを検知したら、
先頭のボタンをSetKeyboardFocusしてフォーカスを戻してあげる処理を用意してあげると良いかと思います。

フォーカスイベントを使ってアニメーション

ゲームらしいUIを作りたい人はアニメーションを使いたくなる人もいるかと思います。
その場合はフォーカスイベントを使用するとフォーカスされたタイミング、外れたタイミングで処理を行えます。
フォーカス時
OnAddedToFocusPath
フォーカスが外れた時
OnRemoveFromFocusPath
OnFocusLost

キーを追加・変更したい

デフォルトの操作じゃぁ満足できないあなた!!
C++プロジェクトであれば、変更可能です。
やり方は簡単、NavigationConfigを継承して独自のNavigationConfigを用意しFSlateApplicationに設定するだけ
エンジンコード変更する必要なし!!

プロジェクトのModuleRuleに「Slate」を追加

XXX.Build.cs

独自のNavigationConfigのヘッダーファイル

Cpp

独自のFNavigationConfigFSlateApplicationに設定します。
※一度初期化すれば問題ないので今回はGameInstanceのInit関数で初期化します。

 

ソースコードのコメントに書きましたが、KeyEventRules.Empty(); を使っても、アナログスティックでの入力は無くなりません。
どうしても無くしたい場合はGetNavigaitonDirectionFormAnalogInternalをオーバーライドして独自に拡張する必用があります。
もっとNaviagetionの仕組みを拡張したい場合はNavigationConfig.hあたりを参考にしてみると良いかもしれません。