みつまめ杏仁

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

UMGのスライダーをシークバー風に変える

先日のツイートを一応メモっておきます。

スライダー道は奥が深いですね。

 

きっかけは @HirofumiSeo さんのこのツイート

 

気になったのでいろいろ試してみるもドラッグ&ドロップでつまづいたので、取り急ぎ現行のスライダーを改造することにした次第。

f:id:hiyokosabrey:20210221103337p:plain

 

ちなみに ちゃんとドラッグできるやつはこちらの @seiko_dev さんのツイート。

 素晴らしいです。

 

今までゲームパッドありきで考える習慣のおかげで、ドラッグ周りの仕様を触ってこなかったのが悔やまれます。

でぼくが作ったのはこれ。

 

 

とりあえず作り方メモ

 

以前にも似たようなのを作ってましたが、ゲームコンフィグのような汎用性はいったん置きにして、1画面に1本想定、後からレイアウト調整がしやすいのを目指しました。

 

マテリアルパラメータコレクションを使います。

f:id:hiyokosabrey:20210221005001p:plain

f:id:hiyokosabrey:20210221005823p:plain

Scalarパラメータを追加。

 

このパラメータを使ってマテリアルを用意します。

f:id:hiyokosabrey:20210221011129p:plain

CollectionParameterノードに、用意しておいたパラメータコレクションをセットします。黄色いのがゲージカラー、グレーが下地のカラーです。

 

1パラメータ1マテリアルになるので、画面に同時に表示するスライダの数ぶんマテリアルアセットを用意する必要が出てきます。同時に表示しないのであれば使いまわせます。

 

次にWidgetブループリント

まずキャンバスを用意

スライダーたちを格納する HorizontalBoxから

f:id:hiyokosabrey:20210221105017p:plain

HorizontalBox に入れるUMGのパーツは3つ。

順番として ButtonSizeBoxButton になるように入れます。

それぞれに子供として、

TextBlockSlider を入れてます。

f:id:hiyokosabrey:20210221012919p:plain

プロパティを触るのは最小限にしたいので、なるべくデフォルト設定でレイアウトします。

 

HorizontalBox は中身に合わせて自動的にサイズを合わせる Size to Contents を有効にしておきます。

f:id:hiyokosabrey:20210221015200p:plain

 

  

 

スライダーの長さを調整する際の肝になるのが SizeBox

f:id:hiyokosabrey:20210221013650p:plain

Width Override で決定します。

 

UMGでは、HorizontalBox の子として、直接 Slider を入れると Slider の持つ Canvas Panel Slot が置き換わってしまう仕様になってます。おかげでサイズがちゃんと認識されなくなってしまうのを解決するためにSizeBoxでくるむことにしました。

 

↓左が通常時、右がHorizontalBoxの子にしたときの状態。

f:id:hiyokosabrey:20210221110440p:plain

このへんオートレイアウト系のしくみなので、おそらく何か理由はあると思いますが、スライダーのサイズ情報が別の Slot にあればよさそうではあります。

f:id:hiyokosabrey:20210221110515p:plain

 

 

スライダーの長さは SizeBox に任せるとして、見た目を整えていきます。

 

スライダーのパーツはシンプルな構成で2つ。

f:id:hiyokosabrey:20210221112606p:plain

 

Detail(詳細) パネルの Style の項目に Normal Bar ImageHovered Bar Image があります。

f:id:hiyokosabrey:20210221015456p:plain

Image のところに、用意しておいたマテリアルをセットします。

Normal は通常時、Hovered は マウスカーソルが上に乗った時を意味します。Normalの方の Tintカラーを少し暗くすると、操作したときに効果がわかります。

Disabled はスライダーが無効な時の状態ですが、条件的にあり得る場合はここにも同じようにマテリアルをセットしておきます。

Bar(溝) の下に 続けて、Thumb(つまみ)の設定と、Barの太さの設定。

f:id:hiyokosabrey:20210221112722p:plain

つまみのビジュアルはここで消します。

Draw As を None にすることで描画はされなくなりますが、Image Sizeは生きていて、Barの見た目の長さに影響するので、ゼロ にします。

f:id:hiyokosabrey:20210221113418p:plain

スライダーの長さにこだわるのは、スライダーで扱う最大値とピクセル表示量の差をできるだけ整数倍にしやすくするのが目的です。計算の仕組み上仕方がないと分かっていても、見た目に「わかる」「わからない」は重要です。にんげんだもの

というわけで、エンジンのお気遣いは排除します。これで単純に SizeBox の値だけでコントロールできるようになりました。

 

スライダーの設定はこれで終了。

次は 再ヘッダ的なカレント位置を示す TextBlock

 

f:id:hiyokosabrey:20210221104637p:plain
中央揃えf:id:hiyokosabrey:20210221012359p:plain にします。

数字と|は間に改行を入れて2行にしています。

行間は Line Height Percentage で調整できます。

f:id:hiyokosabrey:20210221121600p:plain

ブループリントから書き換えるので、 Is Variable を有効にするのも忘れずに。

f:id:hiyokosabrey:20210221121812p:plain

このTextBlockは ゲージの左端に合わせて座標を決めます。実際に動かす際は、RenderTransloation を使って相対的に動かすので、この初期位置だけを合わしておけばOK。

 

これでキャンバスの準備はできました。

次にWidgetブループリント

Float型の変数を作って、Event Pre Construct につないでセットします。

セットする値は、 SizeBox から取得します。

f:id:hiyokosabrey:20210221122729p:plain

もう一つ スライダーの最大量を保持する Float型の変数を追加。

f:id:hiyokosabrey:20210221125908p:plain

ついでにスライダーのプロパティもここで変更します。

 

スライダーの変更を見た目に反映する関数を作ります。

Bar部分にセットしたマテリアルを更新。

f:id:hiyokosabrey:20210221130809p:plain

テキストの内容とポジションを更新。

f:id:hiyokosabrey:20210221130818p:plain


ほぼこれで完成です。

試しに Event Construction に関数をつないで確認してみます。

f:id:hiyokosabrey:20210221135828p:plain

 

レベルブループリントからViewportに追加して再生します。

f:id:hiyokosabrey:20210221132854g:plain



あとはボタンを押したときの処理。

UI的には Numeric Stepper に相当します。

編集画面を Designer に切り替えて、Button のDetailタブ(詳細)からイベントを作成します。On Clicked のプラスボタンをクリック。

f:id:hiyokosabrey:20210221134525p:plain

イベントグラフにイベントノードが現れます。

f:id:hiyokosabrey:20210221135111p:plain

ここにクリックした際のふるまい(挙動)を用意します。

f:id:hiyokosabrey:20210221135359p:plain

 

再生して確認します。

ついでにボタンのテキストも変えてみました。

f:id:hiyokosabrey:20210221140051g:plain

 

改造は以上です。

 

実は UIデザイナー向けのポートフォリオUE4で作ろうというプロジェクトを目論んでいるので、ちょうどよいものができました。

スライドの切り替え等に使えそうです。

 

 

ここからはスライダーに関しての考察とかなんとか

スライダーといえば、ゲームコンテンツの話に限ると、遊びやすさをカスタマイズするためのセッティング画面で見かけるものがほとんどで、その用途はたいてい音量を調整するためのもの。他の要素もスライダーの形式をとりつつも、ステップ(刻み)がサウンドほど細かくないので、スライダーである必要がなかったりします。

 

用途と操作するデバイスによって有利不利があるので、全て書ききるのは文字量がえらいことになりそう、というか今はちゃんと整理できてないので、またどこかでまとめてみたいと思います。

 

UE4 の UMGに用意されているスライダーは、音声ボリュームの調整を主用途として想定されている印象。

クリックした際に、ポイントした位置につまみが移動するのは、今の位置から微調整したいわけではないのでは?と推測します。音量って、ステップ(変化の刻み)が細かくてちょっと動かしたぐらいでは、差異がわかりにくいのもあるのかなと思います。

よく見かける3つのボリューム SE、BGM、VOICE  のバランスをミキサーのように扱うからこそのスライダーだと考えると、精度というよりは比較を優先しているのかなと。

 

また、スライダーUIにとって、つまみの大きさと見た目は大変重要です。

マウスのような手首や腕で操作するデバイスでUIを細かく操作するのは、なかなか鍛錬が必要ですし、ゲームパッドに至ってはスライダーはフリーカーソルと並んで操作が面倒なUIの上位にくるやつです。それぞれでつまみに対する最適なサイズがあります。

 

今回の事案で、いくつか設定されている機能要件の中に、

つまみをマウスボタンで押下しただけでは動かない

つまみ以外でクリックしたらその場所につまみがジャンプする

の2つがあります。

 

仮に一つ目の要件を満たしていたとしても、

つまみのサイズ小さくしすぎるとカーソルを合わせにくくなり、ジャンプしやすくなるので要件を満たすのは難しくなります。

大きすぎると、そのぶん離れた位置にしかジャンプできなくなります。

なかなか興味深い悩みです。

 

つまみの大きさについては、マウスを操作する方のシチュエーションとスキルによって決めていくことになると思います。

センサーの分解能や、カーソルスピードも関係します。ボタンを押下したときにマウスが動いてしまうとかも対策が必要かもしれません。

 モニタの大きさと解像度の関係も大事です。

 

こういった用途や使う人に合わせて細かいチューニングが必要なのが、UI開発の面倒くさいとこでもあり、また面白いとこです。

常に最適解を求めていくのが大事という志向なので、基本、「使いまわし」 は考えないようにしています。使いまわすのはパーツやアセットではなく経験則。

実際に試してみると、気づかなかったいろんな事象がチラチラするので、試行錯誤はやってやりすぎるということはないなと思っています。

 

にしてもUE4のドラッグ周りの仕様が少し見えてきたので、もっと検証してみたい。マルチプラットフォーム開発は、特定のデバイスに例外的に対応するのは避ける傾向があります。最大公約数というかベン図の重なったところで答えを見つけようとするので、どうしてもそのデバイスの性能をどこかで切り捨てているのも事実。パズルのようで難しいですがうまく解決できるように、いろんなアプローチを試していきたいですね。

 

なんか長くなりましたが今回はこの辺で

 ではでは

ステキなスライダーライフを!