アヒルのある日

株式会社AHIRUの社員ブログです。毎週更新!社員が自由に思いついたことを書きます。

UE5のListViewからFocusableを外す方法

こんにちは!おもろいプログラマです。

今回はUE5での仕事中にハマった問題についての解決方法について書いていこうかと思います。 内容はタイトルの通りですがUE5(UE4)のListViewからFocusableを外す方法です。
 
 
まず、ご存知かもしれませんがListViewについての説明です。
(ご存知の方はスキップしてください)

ListViewはwidgetの一つで、実行時の見た目上ScrollBoxと同じような見え方をしますが、内部的には全くの別物で、
//-----
ScrollBox
・全要素を子として持ち、表示領域外のwidgetは非表示になっているだけ
 →要素数が膨大だと、処理負荷が増える
ListView
・画面上に表示される要素数だけを内部的に生成し、表示される内容を差し替える処理を行ってくれる
 →要素数が膨大でも、処理負荷はほとんど変わらない
//-----
となっており、ゲーム制作時では特に要素が多い項目(アイテムなど)で使用することが多いかと思います。
 
 
さて、本題ですがこのListView君、widgetが持つFocusableをfalseにしてもUEのFoucus機能が切れません。

ゲームによってはFoucus機能を切って独自の操作にて個々のリストを動かしたいこともあり、そうなるとこのFoucusが切れない問題は致命的です。

こちら、ズバリ直接の原因はListViewで内容表示に使われているSListViewの設定が問題になっている可能性が高いです。

このSListView、所持しているメンバ変数
bHandleDirectionalNavigation
bHandleGamepadEvents
これらがtrueの状態だと、内部処理にてキー入力やパット入力が行われた際にFoucus同等の振る舞いを行ってしまうようです。
この振る舞いではFocusableのフラグは確認されておらず、Focusableがfalseであろうとユーザーの入力に反応してしまうといった形です。

つまり、問題解決にはこれらの変数にfalseを入れれば良いだけなのですが、 この変数は初期化時にしか設定できず、その初期化はListViewBaseで最適化されているため、そのfalseにするのがかなり面倒です。
 
 
対応方法ですが、まず前提としてC++でのコーディングはほぼ必須です。
BPでも組めなくはないかもしれませんが、ListViewの処理をBPで作り直す事になるかと思いますのでオススメはできません…。

標準的な方法としては、ListViewの派生クラスを作成し、MyListViewの初期化を上書きする形となります。 その際、いくつか新規実装などが必要になるので、結構コストは高めです。

もし、エンジン側のコードを触る許可が降りるのであればListViewBaseでの初期化に上記フラグをoffにする記述を追加するのも解決方法の1つです。 手っ取り早い方法にはなりますが、影響は大きくなりますので問題が無いかを確認の上、対応してください。  
 
さらに具体的な対処方法については、今回書くと長くなりそうなので、リクエストがあれば次回に記載しようかなといった具合です。
(次回更新は2ヶ月先とかになるので、急ぎの場合は、会社の方に連絡いただければ…)

同じ問題に遭遇された方の問題解決の一助となれば幸いです。

ではまたー。