ゲーム制作まで書くブログ

読まないで><

UE4_ウィジェットをゲームパッドでもキーボードでもマウスでも操作可能にする方法_最終章

ついにできた。

UE4ウィジェット

ゲームパッドでもキーボードでもマウスでも

操作できるように

してやったわ!!!!!!!!!!!!!!!!!!!!

様々なサイトの情報をブレンドして作ってやったわ!!!!!!!!!!!!!!!!!!!

 

さすがに今回は

他の人にも読んでもらえるように

丁寧に書いていく。

 

この記事の実装をするとできるようになること

UE4ウィジェットで設定したボタンの配置が縦横の軸でかぶっていれば

 マウスカーソルじゃなくても、キーボード、パッドからも操作可能になる

・選択中は不透明度1で、非選択中は不透明度0.5になる

・スペースやXBOXコントローラーのAボタンで決定になる

・フォーカス中のボタンから別のボタンに移動すると音が鳴る

 

※注意

・カーソルのホバー時に画像が変わったりする処理をボタンのアピアランスで設定できるけど、それは今回の処理を実装してもパッドからはできなかった。

・バージョンは4.25

・当方には知識皆無なので質問しないでください。

・あと参考にしたサイトは最後に書くとして

いじっていくゲームについては

udemyの講座で作ったゲームを基にしている

 

 

 

  • ボタンを配置する

ウィジェットでボタンを配置

f:id:NeToSuKe:20200906163641p:plain

レベルブループリントで表示処理

f:id:NeToSuKe:20200906164158p:plain

この辺は基本ですな。

 

 

  • レベルブループリントで操作有効化&フォーカス 

レベルブループリントにこんなのを呼ぶ

f:id:NeToSuKe:20200906164316p:plain

いくつか種類があるが、今回はGameAndUIというものを配置。

説明は省く。

なぜか。

説明できないから。

( ^ω^)

いいからさっさとGetPlayerControllerをつなげよください。

f:id:NeToSuKe:20200906165013p:plain

あと操作を有効にした際に、最初にフォーカスするボタンを設定しておく。

ボタンはウィジェットからピンを引っ張ってGETすればいい。

検索にgetとボタンの名前入れたら多分出てくる。

f:id:NeToSuKe:20200906165203p:plain

このSetInput~(長い)

イベントBeginPlayウィジェットを設定した後につなげる(あたりまえ)

自分の場合は、このレベルのbeginplayの最後に置かないと

無限ループが発生して止まってしまう状態だった。

 

 

※めちゃながい

変数を用意

先にウィジェットの中に変数「BeforeBtn」を用意しておく。

型は、ボタンの情報を入れるので

Buttonにする。

f:id:NeToSuKe:20200906165608p:plain

 

配列を作成し、ループさせる

ボタンを配列に格納する

配列って検索したら出てくる「配列を作成」に

getしてきたボタンをぶちこむ。

f:id:NeToSuKe:20200906165746p:plain

順番とかはお好みで。

配列なので上から順番に数字付けられる。

それをウィジェットのグラフ内のイベントtickForEachLoopにつなぐ。

f:id:NeToSuKe:20200906170729p:plain

これでボタンの数だけ確認したり処理する流れができた。

 

ボタンを透明にしたり不透明にしたりする

SetRendetOpacityを2つ用意して、とりあえずターゲットにArrayElementをつなぐ

f:id:NeToSuKe:20200906170922p:plain

片方は0.5

もう片方は1.0にしておく。

あとはどういう時に不透明になればいいか処理を書くのだが

そもそもこの処理は自分が思い付きでやったもので

他の人の「音を鳴らす」という処理に付け足しただけ。

なので、その音を鳴らす処理を先に書く。

 

選択が変わったら、音を鳴らす

ここで、最初に作ったBeforBtnを使う。

要は「直前まで選んでいたボタン」という情報と一致しなかったら

それは選択をしているボタンを変えたことになるので

音を鳴らしてわかりやすくしよう

という意図。

なのでまず、

ブランチとHasKeyboardFocusをつなぐ。

f:id:NeToSuKe:20200906171331p:plain

このLoopから流れてくる処理は、ボタン一つに対しての処理なので

まずそれがフォーカスを持ってるのかどうか確認する。

持ってなかったら、そもそも見る必要ないのでFalseに流す。

 

直前のボタンと比べる

またブランチを置いて

NotEqualノードで、

変数のBeforeBtn、Loopから流れてくるボタン情報ArrayElementを比べる 

f:id:NeToSuKe:20200906171741p:plain

こうなってるはず。

これでもしNotEqualが

「比べたけど一致しなかったよ(True)」を返せば

選択を変更した、ということがわかるので

あとは音を鳴らすだけ。

その前に、BeforeBtnに

今選んでいるボタンの情報をぶち込んで更新をしておかないといけない。

じゃないと、BeforeBtnで毎回比べるのに

直前に選んでいるボタンの情報がどこにもなくなってしまうから。

つなぐとこんな感じ。

f:id:NeToSuKe:20200906172005p:plain

 音を鳴らす前に、BeforeBtnのセットにLoopのArrayElementをつなぐ。

音はウィジェットなので2Dでいいんでないかしら。

 

選ばれているボタンだった場合、不透明にする。

最後に、上の処理の中で、もしボタンが選ばれているボタンだった場合

最初の方に作った、不透明にするノード(InOpacityが1.0のSetRendetOpacityノード)を

つないでやる。

ここなら、「直前に選んだボタンと不一致」と不一致

つまり、選んでいるボタンかどうか判定していて

都合のいいことにFalseから流れてきたらその処理が適応できるから。

たぶん

f:id:NeToSuKe:20200906172344p:plain

こんな感じ。

以上でウィジェットのグラフいじりは終了。

 

疲れてもここで終わると、最後の処理の理屈が頭に入ってこないから

我慢してやって。

トイレはゆるす。

 

  • フォーカス外れたとき用の処理をレベルブループリントに書く

 再びレベルブループリントに戻って(ウィジェットを出すレベルの)

先に出来上がりを載せる。

f:id:NeToSuKe:20200906173155p:plain

 フォーカスが、何かの拍子に

ウィジェット内のどのボタンからも外れてしまった場合は

いくらキーボードやパッドをがちゃがちゃしても

フォーカスは戻ってきてくれないので

フォーカスが外れた場合は、指定したボタンにフォーカスを炊きなおす処理を入れる。

これはイベントTickにつないで、常に監視してもらうことになる。

 フォーカスを復活させる処理を先に書く

f:id:NeToSuKe:20200906173852p:plain

 ブランチのBooleanには、あとで処理をつなぐとして

まあそこに「おいおいフォーカスが無くなってるぜ」て返事を

送ればいいのだな

と思っておけばいい。

あとはイベントbeginplayに書いたものと一緒。

SetInputModeGameAndUI

フォーカス復活時にフォーカスさせたいボタンを指定してやる。

ボタンの出し方忘れたら記事読み直してください。

f:id:NeToSuKe:20200906175219p:plain

 あとは、すべてのボタンのフォーカスがされていない状態を

ANDでつなげてブランチのConditionに渡してやればいい。

フォーカスの状態はHasKeyboardFocus

それがNOTならTrueに流れる。

なんでそのままつなげてFalseにしないかというと

フォーカスが無い状態が、すべてのボタンであった場合

なので

そのままつなぐと、一つでもフォーカスが無くても発動してしまうことになるから。

 

レベルブループリント内に同じようなノードがいっぱいできてしまったので

自分はこんな風にならべて、できるだけ同じものからピンを引っ張るようにした。

f:id:NeToSuKe:20200906175830p:plain

最初にも言ったが

udemyの講座で作ったゲームを基にしているので

この記事で出てこなかったノードはその時に作ったもの。

 

人によっては設定が違うので

この方法では解決しないかもしれない。 

 

わかりにくいが、こんな感じになるgif

f:id:NeToSuKe:20200906180239g:plain

画像の変更ができなかったので

カーソルの時とパッドの時で対応が違う。

まあ違いが判っていいかなって思ってる。

 

 

 参考にさせていただいたサイト