みつまめ杏仁

アンリアルエンジン(UE4)でGUIを作るためにゴニョゴニョしてます。UIデザイナーの皆様の助けになれば幸いです。

キーリピート機能をつくってみる

 パソコンでキータイプしていると気づくこともあると思いますが、カーソルキーとか同じキーを押しっぱなしにしたときに、1文字目と2文字目の間にちょっとだけ間があります。タン、タタタタタタ・・・・・・ 初めてパソコンを触ったとき、当時子供だった私はモヤモヤした経験を覚えています。UIを意識するようになってようやく腑に落ちたものです。

f:id:hiyokosabrey:20180204094046g:plain

 ゲームでも、音量調節のスライダーなんかにごく当たりまえに実装されているので、身近なやつを見れば・・・って、最近はタッチデバイスなのであまり身近じゃないですね。でもまだPS4とかゲームパッドで遊ぶUIはあるので、今回ブループリントで作ってみました。

 

UMG

キーリピートの挙動を見るために、シンプルなボリュームスライダーを用意します。

キャンバスに3つのパーツを配置します。

f:id:hiyokosabrey:20180203125755p:plain

f:id:hiyokosabrey:20180203125802p:plain

右端がMAX想定なので、ツマミは左端に置きます。

 

ブループリントから触るので3つとも Is Variable にチェックを付けます。

f:id:hiyokosabrey:20180203130034p:plain

触るといっても、Image_Baseだけはサイズを取得するだけです。

 

 

Widgetブループリント

変数を2つ用意します。

f:id:hiyokosabrey:20180203130610p:plain

 

まずは、スライダーの移動範囲を調べて変数に入れます。

f:id:hiyokosabrey:20180203131734p:plain

すでにキャンバスに置いているパーツの長さを調べるので、Event Pre Constructで問題ないです。Get Size で調べたImage_Base(ラインみたいなやつ)の長さを変数 MaxPos に Set します。これは、後からデザインやレイアウトが変更になっても、キャンバスを調整するだけ(Blueprintは無傷)で済むのでオススメです。ひと手間かかってますが、こういったつくりは後で地味に効いてきます。

 

次に関数を2つ用意します。

まず一つ目は指定した値の場所にツマミを移動して、値を表示する関数になります。

f:id:hiyokosabrey:20180203132503p:plain

便利な Lerpノードを使います。AとB2つの値を線形補間したうえで、Alphaの値に応じた途中の値を返してくれるノードで、MaxPos を Bのピンにつなぐことで、どんな長さのスライダーでも対応できるようになります。MaxPosはパーツの長さを調べてるのでデザインが変更されても、勝手にこのBの値が変わっていることになります。

 

 もう一つは初期状態の値をもらう関数です。

f:id:hiyokosabrey:20180203193152p:plain

 ゲームでは設定した値をセーブしているのが普通なので、まずは初期値を受け取れるように関数で用意します。この int型の Value という変数は、念のため Private にチェックをつけておくと安全です。

 

関数が用意できたら、今度はマクロを用意します。

受け取った値を Valueに加算して、0~100の範囲を越えないようにします。

f:id:hiyokosabrey:20180203193901p:plain

越えたらループするようにしています。

減っていくとき、3 → 2 → 1 → 0 → 100・・・

増えていくとき、98 → 99 → 100 → 0・・・

このWidget以外から呼ばれる処理ではないので関数ではなくマクロにしました。

 

仕上げにイベントを用意していきます。

カスタムイベントを2つ置いてマクロと関数をつなぎます。

f:id:hiyokosabrey:20180203194836p:plain

引き算のノードを使わなくても、マイナスの値は、足し算することで引き算と同じ結果になります。汎用性の高いマクロや関数を作るときに応用できます。

 

Widgetは完成です。

次は動かすためにレベルブループリントを編集します。

 

 

レベル

おなじみのやりかたでWidgetをViewportに追加すると、表示された瞬間EventConstructが動くので、先に初期値を渡しておきます。

f:id:hiyokosabrey:20180203195847p:plain

試しに再生してみると、

f:id:hiyokosabrey:20180203200040p:plain

ちゃんと反映されていればOK。

 

 

では、キーリピートの処理を作ります。

必要な変数を用意します。

f:id:hiyokosabrey:20180203225924p:plain

まず、float型の変数は、キーリピートの間隔を保持します。スライダーが増えるか減るかをフラグで管理するためにBoolean型の変数を。一番上の RepeatTimerHNDLという名前の変数はTimerHandle型の変数で、Set TImer Event ノードの戻り値 Return Value ピンからPromote to Variable すると簡単に作れます。

 

カスタムイベントを用意して、下のようにつなぎます。

f:id:hiyokosabrey:20180203230620p:plain

右端のノードは、Widgetに作っておいた関数を呼び出しています。増えても減っても基本的なキーリピート処理は変わらないので、極力使い回せるものは使い回すようにしています。

続きはこのようになっています。

f:id:hiyokosabrey:20180203231752p:plain

 DoOnce ノードでキー入力初っ端だけ通すようにして、2回目以降のリピート間隔を float型の変数にセットしています。

 

まだ続きます。DoOnceはリセットすることができるので、キー入力をやめたらリセットするようにつなぎます。下図はカーソルキーの左右を押した場合です。

f:id:hiyokosabrey:20180203232534p:plain

 

これで完成です。

さっそく 動かしてみましょう。

f:id:hiyokosabrey:20180204084434g:plain

キー入力を開始して、ひと呼吸置く感じで動きます。

 

基本的な仕組みはイベントの自己呼び出し。 f:id:hiyokosabrey:20180204085027p:plain

あとは、DoOnceノードで、RepeatInterval 変数の値を 0.75 から 0.025 に変えます。

これでキー入力後の《 間 》が作れたことになります。この値は 1.0  が1秒です 。フレームレートによりますが 60fpsだと、0.0167 くらいで 1フレーム分です。これを変えてみるといい感じに調整できますよ。

 

この《 間 》が無いとどうなるか、0.75 をセットしてるとこを 0.025 にしてみると答えが分かります。

 

次回は、せっかく作ったスライダーをいくつか並べて操作できるようにしてみようと思います。

 

ではでは

ステキな キーリピート ライフを!