みつまめ杏仁

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

横方向のアイテム選択UI 《おまけのオマケ》

4.19がリリースされましたね。楽しみですがまだ落としてないので、引き続き 4.18.3で書いてます。前回のおまけに続いてさらにオマケを作ってみました。今回は ロックとアンロックの状態切り替えを組み込んでます。

f:id:hiyokosabrey:20180316234046p:plain

 ロック状態であることを分かりやすくすることで、解除したくなる心をくすぐる仕掛けです。完全に隠さないことでゲームのプレイ寿命を延ばす効果があります。この仕組みだと、あらかじめロックされているのを見せているので、解除されたことをことさら明示する必要がないのも特徴です。

 ネタバレなので表示したくないとか、アップデートなんかで後から物理的に追加される場合もあるので、隠さないといけない場面も多々あります。

 完全に隠す場合、何が増えたか気づきにくいので、New 的な表示が必要になります。さらにNew的な表示はその表示を消すタイミングと、セーブデータに反映する仕組みも必要になるので、比較的制作コストと不具合のリスクが高くなります。

 今回は隠さずに表示しておいて選択できないタイプで進めます。

 

まずは、鍵アイコンを用意します。

f:id:hiyokosabrey:20180316235447p:plain

この手前の面にカギ穴のあるタイプの錠って、ほとんど見かけないんだけど、ここにないとバッグに見えてストアのアイコンと間違われるから仕方ないんだよな、たぶん。

 

イコン画像ができたところでアイテムパーツのWidgetから編集していきます。

 

WD_Item

f:id:hiyokosabrey:20180316235708p:plain

LOCKされている場合は暗くすることにします。

最初に呼ばれる関数 setupItem にBoolean型の引数をひとつ追加します。

それをSelectノードを使って2色を振り分けます。

f:id:hiyokosabrey:20180317000022p:plain

このWidgetは以上です。

次はフォーカス表示用のWidgetです。

 

WD_ItemFocus

f:id:hiyokosabrey:20180317000228p:plain

キャンバスに鍵アイコン用のImageを追加します。

f:id:hiyokosabrey:20180317000454p:plain

ZOrderは、アイテム画像とタッチおよびクリック検出用のボタンとの間にします。

 

ロックされているアイテムは暗い状態のままアニメーションさせつつ、鍵アイコンの表示をアニメーションの中で切り替えます。

ちょっと楽したいのでフォーカス時のアニメーションを複製して、ロック状態専用のアニメーションを用意します。

f:id:hiyokosabrey:20180317001002g:plain

ブラーパネルを追加しても面白そうですがキャンバスはこの辺にしておきます。

 

次にGraphの編集に移ります。

鍵アイコンを初めからチラ見せする訳にはいかないので、しっかり非表示にしておきます。

f:id:hiyokosabrey:20180317001113p:plain

 

新しくBoolean型の変数を用意します。

そしてフォーカス演出のイベントにBoolean型のピンを追加して、その値を用意した変数で受け取り(セットのかたち)します。

f:id:hiyokosabrey:20180317002354p:plain

それをブランチノードの分岐で利用します。下図は続きです。

f:id:hiyokosabrey:20180317002818p:plain

このイベントの全体は以下のようになります。

f:id:hiyokosabrey:20180331195747p:plain

 

 

で、さらにタップかクリックしたときの決定演出イベントでも分岐を入れます。

f:id:hiyokosabrey:20180317003041p:plain

ロックされていれば、タップしても無視するようになります。

以上でフォーカス表示用のWidgetは編集完了です。

 

最後に親のWidgetです。

 

WD_ItemList

f:id:hiyokosabrey:20180317003346p:plain

 

ロックとアンロックのテーブルをBoolean型の配列で用意します。

f:id:hiyokosabrey:20180317003857p:plain

このテーブルの内容を、アイテムを並べる際に渡します。

f:id:hiyokosabrey:20180317004232p:plain

もう一か所同じように、テクスチャとブール値を渡すところがあるので、このGETノード2個をマクロにしてしまいましょう。下のように4つのノードをハイライトして、

f:id:hiyokosabrey:20180317004605p:plain

右クリックすると、コンテキストメニューが出るので、Collapse to Macro を選びます。

f:id:hiyokosabrey:20180317004705p:plain

するとこうなります。↓

f:id:hiyokosabrey:20180317004813p:plain

いろいろ名前が分かりにくいのと、左側のピンはどちらも同じ値でOKなので、1本にまとめたいので、ダブルクリックして編集しましょう。中身はこんな感じにします↓

f:id:hiyokosabrey:20180331202334p:plain

マクロの編集が終わって戻ってくると、なにやら不穏なことになっている様子。

f:id:hiyokosabrey:20180317005235p:plain

Inputのピンを強制的に1つ減らしたせいです。

左の赤いラインを消して(Altキー押しながらラインを左クリック)あげると正常になります。

 

さっそくこのマクロをSetFocusItem の関数でも使います。

f:id:hiyokosabrey:20180317005918p:plain

↑Before   ↓After

f:id:hiyokosabrey:20180317005636p:plain

編集は以上です。

 

動作を確認してみましょう。

f:id:hiyokosabrey:20180317010937g:plain

今回はロック・アンロックの表現ですが、所持金と販売額を比較して最初のセットアップ関数でフラグ(Boolean)テーブルを作れば、ショップの表現に転用できそうです。

アイテム名に《未購入》とかの文字列をくっつけたり、ロック状態のアイテムを決定すると、ストアに飛ばすのもいいかも、いや良くないか・・・ダイアログだせば・・・などと考えてみたり。

 

 UIの開発って、結構ロジカルで地味だと思うんですが、こういったちょっとした振る舞いで、ユーザーの心象をある程度操作できるので、難しいし奥が深くて楽しいですよね。

 左右のボタンを押したときのスクロール方向を逆にしてみたりするとまた違う印象で楽しめます。(なんか違和感!という気づきがあったりします)あのお風呂の湯船に足を入れるのはどちらの足か? みたいな無意識に操作してて当たり前になってることを改めて見直すと、新しいUIの発見があるかもです。

 と、なんだかまじめな話になってしまいましたが、今回はこの辺で。

 

ではでは

ステキなロック表示ライフを!

 

 

 

横方向のアイテム選択UI 《おまけ》

 昨日家に帰ってから寝落ちしつつ作ったので、なんか文体がおかしい気もしますが無事 喜んでいただけて良かったです。モノ自体はだいたい1時間ほどでできました。アイコンの素材探しと、記事を書くのに時間がかかりましたが、UE4でのUMGユーザーが増えることを願ってこのブログを始めたので楽しく書かせてもらいました。しかもネタもできてうれしいです。

f:id:hiyokosabrey:20180316030052p:plain

 さてさて、決定したときの処理が無かったので、軽いやつを作ってみました。まずはフォーカス表示用のWidgetから。

 

WD_ItemFocus

f:id:hiyokosabrey:20180316023907p:plain

ちょっとトリッキーなつくりかもしれないですが、Buttonパーツを使います。

これをキャンバスの子供に追加します。ZOrderはアイテムの画像より手前で。

f:id:hiyokosabrey:20180315212243p:plain

これを透明にします。

f:id:hiyokosabrey:20180315212512p:plain

HiddenやCollapseなどの非表示設定にしてしまうと、キャンバスに存在しないことになって、タッチやクリックを検出しなくなるからです。

Buttonをこのように上からかぶせない方法もありますが、ちょっと手軽じゃないので今回は簡単なやつでいきます。

前回の記事に書いた方法で、onPressedイベントを使います。

f:id:hiyokosabrey:20180315213938p:plain

そして、タッチまたはクリックしたことを通知するためにイベントディスパッチャーを使います。

エディタウィンドウの左にあるMyBlueprint タブの中にあります。

f:id:hiyokosabrey:20180315214528p:plain

通知するだけなので適当に名前を付ければOKです。

今回タッチまたはクリックしたときのリアクションに短いアニメーションも作りました。

f:id:hiyokosabrey:20180315215115g:plain

これを onPressedのイベントにつなぎます。

f:id:hiyokosabrey:20180315215446p:plain

 

これで完成。

つぎはこの通知を受け取るWidgetを編集します。

 

 

WD_ItemList

f:id:hiyokosabrey:20180316023855p:plain

ForloopノードのCompletedピンからの続きに、バインドノードをつなぎます。

f:id:hiyokosabrey:20180315215657p:plain

フォーカス表示用のWidgetはすでにキャンバスに置いてあるので、Getの形でGraphに置いたら、「Bind」で検索するとイベントディスパッチャーを追加したときの名前が見つかります。そのバインドノードには Eventピンがあるので、ここにカスタムイベントをつなぎます。

f:id:hiyokosabrey:20180315223303p:plain

これで、中央のアイテムをタップかクリックすると、アイテム名がデバッグ表示されるようになります。今回はサンプルなのでここまでにしていますが、買ったり使用したりといった処理がこのあと続くと思います。さらに上位のWidgetに通知することもできます。

 UE4で UIを作る場合、複数のWidgetをパーツとして組んでいくので、このブループリント間で連絡しあう仕組みがとても活躍します。普段親から子に対しては、親が一方的に子に指示をして子はそれに応えることしかできません。ところがイベントディスパッチャーを使うと、「バインド」で親が子にケータイを持たせて、子から自身のタイミングで親へ連絡させることができます。

 

 とりあえず軽いやつですが汎用的なつくりですので、後はアレンジとか応用になるかなと思ってみたり。

 

 スワイプまたはドラッグでのスクロールについては、そういった操作に対応できるノードが用意されているので作れそうですが、今回の構造に追加するのはちょっと難しいです。最初から設計を変えて作り直した方がよさそうですね。

 

 ではでは今回はこの辺で

ステキなEventDispatcherライフを!

 

 

 

 

横方向のアイテム選択UI

今回はコメントを頂いたのでその返答として書きます。コメントいただけると嬉しいですね。続けてきた甲斐があるってものです。

で、作ってみたのはこれ。

f:id:hiyokosabrey:20180314225501p:plain

いくつかのアイテムを左右にスクロールさせて選択するメニューUIです。

今回アイテムの絵素材として FLAT ICON DESIGNさんとこのを使わせていただきました。

3つのWidgetアセットで構成します。

まず、選択用に並べるパーツとしての Widgetとフォーカス状態を表すWidget

f:id:hiyokosabrey:20180314231253p:plain

そして、これらをまとめるWidgetです。(※名前は適当です)

ではさっそく、並べる方から用意していきます。

 

WD_Item

UMGのキャンバスはシンプルです。

f:id:hiyokosabrey:20180314231737p:plain

並べた時にくっつきすぎないようにCanvasPanel (Sizeは120x120)を置いて、中にImage を子供にして配置します。

f:id:hiyokosabrey:20180314232130p:plain

 

つぎにGraphを編集します。

 

テクスチャを受け取る関数を用意します。

f:id:hiyokosabrey:20180314232410p:plain

次にカスタムイベントを用意します。

f:id:hiyokosabrey:20180314232618p:plain

これはフォーカスされているときと、されていない時で表示/非表示を切り替えるためのイベントです。カスタムイベント側の緑のピンは、右のSet Visibilityノードにある 緑のピンからドラッグ&ドロップすると、簡単に追加できて便利です。

 

f:id:hiyokosabrey:20180314233104p:plain

以上で並べるためのパーツは完成。

次は、フォーカスされたアイテム用のWidgetを作ります。

 

WD_ItemFocus

これもキャンバスはシンプルな構成で十分です。

f:id:hiyokosabrey:20180314233537p:plain

ただ大きいだけだと面白くないのでアニメーションを仕込んでみます。

f:id:hiyokosabrey:20180314234228g:plain

キャンバスはこの辺で、次にGraphを編集します。

 

アイテムを切り替える際、見えない状態から始めないとタネがバレるので、カラーを透明にしておきます。

f:id:hiyokosabrey:20180314234431p:plain

この Event Pre Construct につなぐと、エディット中から適用されるので、Add to Viewport したときのチラ見えを安全に防ぐことができます。

 

次はフォーカスされて表示を更新するカスタムイベントです。

f:id:hiyokosabrey:20180314234909p:plain

フォーカスされるアイテムはプレイヤーの動作に応じて動的に変化するので、このイベントで、テクスチャを受け取ってアニメーションを再生しています。

 

以上でパーツのWidgetは用意できました。

次に、全体をまとめて管理するWidgetです。

 

WD_ItemList

 まずUMGのキャンバスは以下の構成になります。

f:id:hiyokosabrey:20180315001833p:plain

最初からあるCanvasPanelとは別に、新しく置いた CanvasPanel は、HorizontalBox をクリッピングする(CanvasPanel の外側は描画しない)ために用意しました。後述。

ヒエラルキーはこんな状態

f:id:hiyokosabrey:20210828143615p:plain

 

 HorizontalBox の大きさは、Size To Content にチェックをつけて有効にしておきます。

f:id:hiyokosabrey:20210828143915p:plain

この時点で中身が空なので、左上に縮こまってます。

 

 CanvasPanelの大きさは、実際に表示する大きさなので、アイテムWidgetのサイズと表示個数によって調整します。今回アイテムWidget1個のサイズが120x120で、7個が見えている状態にします。さらに両端に半分が見えるようにしたいので、合計8個分として 120 × 8 = 960 の幅で作成します。両端のチラ見せは、並んだアイテムの続きがあることを印象付けるためです。

 

今回アイテム120x120が 8個 並ぶ想定でサイズを決めました。

f:id:hiyokosabrey:20180315003452p:plain

 

 また、少し前のVerから、キャンバスの外側にも子供を表示する仕様がデフォルトになったので、キャンバスパネルの設定を変更する必要があります。

f:id:hiyokosabrey:20210828143934p:plain

CanvasPanelを選んだ状態でのDetailsタブにClippingの項目があるので、これを探して変更しておきます。 Inherit → Clip to Boundsf:id:hiyokosabrey:20180315003936p:plain

 

最後に、フォーカス表示用のWidgetを、User Created の中から探してキャンバスに追加します。ZOrderの値を大きくして、手前に重なるようにします。

f:id:hiyokosabrey:20180315004834p:plain

これは入れ子にはしません。

 

 

つぎに Graphの編集に移ります。

 

アイテムを半分チラ見せしたいがために、ちょっとだけ表示位置の調整が必要になります。

f:id:hiyokosabrey:20180315011228p:plain

このために、Float型の変数を用意します。

CanvasPanel(CanvasPanelListと命名)のサイズを取得して計算し初期位置を求めます。

f:id:hiyokosabrey:20180315043136p:plain

今回のスタイルのUIは、スクロール方向がキー操作と逆にしているので、アイテムWidgetの表示サイズをマイナスの値で扱うことにします。最初からマイナスにしておくことで計算が一つ減ります。

この辺の事前準備は、必要なパーツも最初からキャンバスに揃っているので、Event Pre Construct で行っています。

 

続いて Integer型の変数を2つ用意します。フォーカス中のIndex番号を保持するためのものと、アイテムを必要個数分生成して追加しつつスクロールの端をチェックするための2つです。

f:id:hiyokosabrey:20180315044247p:plain

まん中の関数は、アイテムの中身をセッティングする関数です。内容は以下。

f:id:hiyokosabrey:20180315045204p:plain

ここはプロジェクトのデータ管理方法によっては違うつくりになると思いますが、この関数で表示するためのアイテムを準備します。

後から追加しやすいことを考えて、テクスチャアトラスは作らず、バラバラで個数分用意しました。

f:id:hiyokosabrey:20180315045851p:plain200x200

それをTexture2D型の配列変数にあらかじめ登録しておきます。

 

大量のテクスチャアセットをインポートする場合に便利なのがこれ↓

f:id:hiyokosabrey:20180315050354p:plain

コンテンツブラウザで、対象の画像アセットを複数選択しておいて右クリックすると選択できます。扱い方はこちらのブログに詳しく紹介されています。

【UE4】Sound Cueのパラメータを一覧して一括変更する方法 - SAT04 CREATIVE SPACE

サウンドアセット用の解説なのでパラメータは違いますが、基本的な操作は同じです。

 

次に、アイテムを並べていきます。 Forloop ノードを使って必要な個数分の処理を回します。

f:id:hiyokosabrey:20180315052035p:plain

Create Widget したあとすぐに WD_Item型の配列変数に追加(Addノード)しています。これは、並べたアイテムを後からIndex番号で扱いたいからです。

HorizontalBoxに子供として追加すると自動的に水平方向(基本的に左から右)に並ぶことになります。

ひととおり並べ終わったら、フォーカス表示用のWdgetにテクスチャを渡すのと、アイテム名の表示を行う関数を用意して、Forloopノード Completeピンにつなぎます。

f:id:hiyokosabrey:20180315053237p:plain

 

次はスクロールの動きを作る関数です。

f:id:hiyokosabrey:20180315054709p:plain

慣れないとややこしそうに見えますが、このブログでもよく登場するやつです。

( 目的地 - 現在地 )×  減速率 を 現在地に足す ことで減速しながら目的地に向かいます。

減速率の 0.25 という値をいろいろいじって加減してみてください。

 

この関数を、Event Tick につなぎます。

f:id:hiyokosabrey:20180315054856p:plain

 

次に、アイテムのフォーカス位置(FocusIndex)を増やしたり減らしたりするイベントを用意します。

f:id:hiyokosabrey:20180315055855p:plain

f:id:hiyokosabrey:20180315055823p:plain

左端のイベントノードは、一つはカスタムイベントですが、もう一つは、ボタンから生成したイベントノードです。作り方は簡単。編集モードをDesigner に切り替えます。

 

キャンバスのButtonパーツを選択した状態でDetailsタブの一番下にEvents という項目があります。この緑色の + ボタンをクリックすると、Graph に出現します。

f:id:hiyokosabrey:20180315060228p:plain

 

このイベントで、FocusIndexの値が更新されたので、見た目に反映する必要があります。最後に関数をつないで完成です。

f:id:hiyokosabrey:20180315055838p:plain

と言いたいところですが、あとひとつ関数を追加します。

f:id:hiyokosabrey:20180315060747p:plain

これはフォーカスを切り替えた際に、非表示にしていたアイテムを戻す関数です。

このイベントの処理を簡単にまとめると、

f:id:hiyokosabrey:20180315061605p:plain

という流れになります。

 

 

さっそくテストしてみましょう。

レベルブループリントから、ビューポートに追加します。

f:id:hiyokosabrey:20180315061857p:plain

これで再生すると動きますが、キーボード操作用のイベントも追加しておきます。

f:id:hiyokosabrey:20180315062108p:plain

 

再生してみます。

f:id:hiyokosabrey:20180315063010g:plain

 GIFなのでブラウザによっては速度がでないかもしれないですが、結構いい感じになったと思うのですがいかがでしょうか?左右の端に行くとループしているので反対側に一気に飛びます。

左右にある灰色の四角はUMGに用意されているもので、グラフィックを設定していないので、見た目はショボいですがちゃんと反応します。

 

今回決定処理はないですが、ひとまずそれっぽい挙動は作れたかと思います。

説明が分かりにくいところとかあればツッコミコメントをお願いします。

 

ではでは

ステキなアイテム選択UIライフを!

 

スピンボックスも作ってみた

 前の記事でインターフェイスを作りましたが、せっかくなのでスピンボックスも作ってみることにしました。

 スライダー同様、ゲームの設定画面とかでよく見かけます。スピンボックスはGUIの1スタイルでMicrosoft Developer Networkのドキュメントに簡単な説明があります → スピンボックス

 

 ▲と▼をクリックするたびに値が1段階変化します。数値を増減させるときに便利なのですが仕組みとしてテキストなどの文字列を入れて使われることもあります。数値のみの場合は明確に区別するために、 Numeric Stepper と呼ぶこともあるようです。

f:id:hiyokosabrey:20180225110925p:plain

 テキストの場合は、序列や段階を意図した言葉選びが重要です。したがって、このUIのメリットは  選択中の状態が分かりやすい ことと、その前後の内容が予測しやすい ことにあります。なので、増減と関連性のない、前後の脈絡のないテキストを選択肢にすると、複数ある選択肢の全体が把握しづらいため一通り送って確認しないと選べないので時間がかかります。

f:id:hiyokosabrey:20180225111352p:plain

ゲームクリア後や実績解除などで、後から選択肢を追加しても画面のレイアウトに影響がないので、開発者にとっては都合のいいUI だったりします。でも途中で内容が増えても気づかないので、Newマークを付けたり、お知らせ表示を入れたりと、開発側としては結局手間がかかることに・・・。用法容量を守り正しく活用したいものです。

 このへんがデメリットとなって使いづらさにつながるので、段階や序列のないテキストを選択肢にする場合はコンボボックスやリストボックスがオススメです。もちろん表示に余裕があれば全部並べて選択させるのがベストです。ゲームのUIってほとんどが選択肢と言っても過言じゃありません。なんらかの選択をユーザーにさせてユーザーの意思を尊重しているかのようにふるまいつつ、都合の悪い選択肢なんて最初から無かったことに・・・うわやめろなにを・・・ゴフゥ・・・中断

 

 

 

 げふげふ(さてさて)、

 今回はスライダーなどと操作方法を統一するために ↑ ↓ キーで項目を選んで、←→キーで内容の切り替えを行うようにします。レイアウトはスライダーと同じように並べるので↓のようになります。

f:id:hiyokosabrey:20180225104855p:plain

新しくWidgetを用意してもいいですが、スライダーWidgetと共通の部分が多いので複製します。

 

 

UMG

f:id:hiyokosabrey:20180225185602p:plain

不要なパーツを消してテキストブロックに置き換えます。

テキストブロックは is Variable にチェックを付けるのを忘れないように。

 

 

Widgetブループリント

必要な変数を用意します。複数の選択肢を扱うので、その個数を保持する integer型の変数と、受け取った選択肢用の Text型の配列変数です。

f:id:hiyokosabrey:20180225190516p:plain

値を受け取る初期設定用の関数 initValue は ↓ のように変更します。

f:id:hiyokosabrey:20180225205556p:plain

 

 値を見た目に反映する関数 updateValue の中身は受け取った配列の中身を取り出すだけなので、 ↓ のようになります。

f:id:hiyokosabrey:20180225204654p:plain

配列のエラーチェックをする場合は IS VALID INDEX ノードが便利です。

f:id:hiyokosabrey:20180225205155p:plain

 

値をアイテムの数だけでループするようにするので、rangeCheck マクロを編集します。

f:id:hiyokosabrey:20180225210010p:plain

 

これでコンパイルしてエラーが出なければ完成。

 

制御用Widget

キャンバスにできたスピンボックスのWidgetを追加します。

f:id:hiyokosabrey:20180225210528p:plain

初期化の関数に追加します。

f:id:hiyokosabrey:20180225210727p:plain

選択肢用のアイテムはここで、Make Arrayノードで渡します。

 

アクティブなWidgetを切り替える関数にも追加します。Switch on Int ノードをAdd pinして割り込ませます。

f:id:hiyokosabrey:20180225210917p:plain

 以上です。メンバーが一つ追加になったのにこの簡単さ。これもインターフェイスのおかげです。

さっそく再生してみましょう。

f:id:hiyokosabrey:20180225212445g:plain

 

これでどんなセッティング画面が来ても対応できそうな気がしてきました。

あと必要そうな処理としては、制御用Widgetに値を返すようにしたり、変更内容をリアルタイムに反映したいときのために イベントディスパッチャーを用意したりすれば完璧な予感。

なんかUIって、表のグラフィックデザインにスポットが当たりがちですが、実際はこういった地味な内部処理が頑張ってたりするんですよね~ とか呟いてみたり。

コンポーネントとして用意されているので、わざわざイチから起こさなくても・・・

という声が聞こえてきそうですが、やっぱり仕組みを知ることで、次の新しいUIが生まれてくる気がするんですよ。

 

今回インターフェイスは使い回したので説明はしてませんが、汎用的なやつが一つあれば結構いろんなUIパーツに適用できるのでおすすめです。

 

というわけで今回はこの辺で。ツッコミとかリクエストとかあればコメントください。

ではでは

ステキなBPインターフェイスライフを!

 

 

 

スライダーUIを並べて操作してみる 《おまけ》

キーリピート処理の説明用にスライダーUIを作ってみたら、なんとなくいい感じになってきたので調子に乗って”初期設定に戻す”機能を追加してブループリント インターフェイスまで扱うとこまできたのですが、もうひとつ「ミュート」の切り替えができるようにして完了にしようと思います。

f:id:hiyokosabrey:20180220225350p:plain

 

前回の記事はこちら

 キーリピート機能をつくってみる - みつまめ杏仁

スライダーUIを並べて操作してみる - みつまめ杏仁 

スライダーUIを並べて操作してみる 《続き》 - みつまめ杏仁

 

アイコン

まずはアイコンの仕込みから

 

テクスチャは簡単な2パターンを用意します。2つの画像に分けてもよかったりしますが、今回はマテリアルで切り替えます。

f:id:hiyokosabrey:20180220225549p:plainSize: 96x96

 

画像をテクスチャとしてインポートしたら、そこから Create Material します。

f:id:hiyokosabrey:20180220230054p:plain

UVスクロールさせるだけのシンプルなマテリアルです。

 

 

Interface

インターフェイスにあとひとつ関数名を追加します。

これは A とか 〇 とかの「決定」ボタンを押したときに呼び出すイベント用です。

f:id:hiyokosabrey:20180221223507p:plain

コンパイルして閉じます。

ここでちょっと注意が必要なのが、インターフェイスを編集して保存すると、そのインターフェイスをセットしているブループリント全てが、再コンパイル対象になってしまうということです。

f:id:hiyokosabrey:20180221224142p:plain

なので、UE4を閉じるときに、普段触っていなかったブループリントが「save する?」

って訊いてきて慌てることがあります。インターフェイスを触るときは、心の準備をしてから触るようにしましょう。エラーが出てるとマズいので、アスタリスクのついたアセットは、面倒ですが一度開いてコンパイルしてから閉じるようにします。

 今回のスライダーのWidgetはそのまま編集をします。

 

 

UMG

まずはスライダーWidgetのキャンバスにアイコンを配置します。

f:id:hiyokosabrey:20180220230852p:plain

Imageパーツを表示したいサイズに調整して、作っておいたマテリアルをセットしてやります。

 

Widgetブループリント

つぎにGraphの編集です。

まず、 ブーリアン型の変数 "isMute" を一つ追加します。

f:id:hiyokosabrey:20180221225227p:plain

 

この変数を使って見た目を切り替える関数 "switchMuteDisp" を用意します。

f:id:hiyokosabrey:20180221225613p:plain

今回 ミュートのON / OFF で変更するのは3パーツ。

f:id:hiyokosabrey:20180221230435p:plain

扱う値が違うので結果的に3種類のSelectノードを使うことになりました。

Selectノードは ブーリアン型の値、 True か False を判定して、あらかじめ決めておいた対応する値を取り出してくれる大変便利なノードです。Brunch ノードで組むこともできますが、白いラインが分岐することを考えると、Selectノードを使う方がスッキリして見えます。

つないでみて気づくのですが、テキストのカラーについては SlateColor と呼ばれる特殊なカラー値なので、LinearColor が使えません。さらに面倒なことにSelectノードの上下にならんだピンの扱いがなぜか逆という・・・

 

さてさて 見た目をチェンジする関数ができたところで、初期設定用の関数に追加した変数を加えます。

f:id:hiyokosabrey:20180221231416p:plain

新しく引数(Inputs)ピンも追加。最後に、できたての見た目チェンジ関数をつなぎます。

 

あとはボタンを押したときに呼ばれるイベント。

f:id:hiyokosabrey:20180221231754p:plain

ブーリアン型の変数 isMute の内容をスイッチングします。スイッチングしたあとは見た目に反映するためにつくった関数をつないでいます。

これでスライダー用のWidgetは完成です。

 

制御用Widget

 スライダーWidgetの 初期設定用の関数に引数を追加したので、ノードが変化しているのが確認できます。

f:id:hiyokosabrey:20180221232348p:plain

 

前回の記事でリセットするイベントを作りましたが、そこにノードを追加します。

f:id:hiyokosabrey:20180221232619p:plain

単純にIndexFocus の値が3 以外なら、onDecide のイベントを呼ぶようにします。

これで、できあがりです。

 

再生して確認してみましょう。

f:id:hiyokosabrey:20180221233313g:plain

うまくいきました。

ただこの操作はユーザーが気づきにくいので、画面の隅にでも操作ガイド的なナビ表示があった方いいでしょうね。マウスクリックを受け付けるなら、おそらく直接スピーカーのアイコンを触るので心配なさそうですが、そうなるとアイコンのデザインも、もう少しボタン感のある見た目にしないといけないですね。

 

ひとまずスライダーUIに関してはここまでにします。

ではでは

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

スライダーUIを並べて操作してみる 《続き》

前回それなりにサウンド設定ができそうな雰囲気を醸し出すことができました。

そこにリセット用の項目を追加してみます。

f:id:hiyokosabrey:20180218225034p:plain

右端にもオマケでアイコンを追加しています。

 

 前回の記事はこちら。limesode.hatenablog.com

 ↑これをベースにいじっていきます。

 

Blueprint Interface

今回の肝は、タイプの異なるWidgetを並べて操作できるようにする部分になります。そのための準備として、インターフェイスを用意します。

f:id:hiyokosabrey:20180218225616p:plain

とりあえず ”IF_Settings” と名付けました。

f:id:hiyokosabrey:20180218225841p:plain

ダブルクリックして、エディタ右上にある追加ボタンで関数名を4つ追加します。

f:id:hiyokosabrey:20180218230025p:plain

コンパイルして保存したら閉じます。

 

Interfaceを登録

前回作ったスライダーパーツのWidgetを編集します。

エディタをGraphに切り替えて、Class Settings をクリック。

f:id:hiyokosabrey:20180218230621p:plain

Detailsタブに Interface と書かれた項目があるので、そこの Add ボタンを押して、

さきほど用意した IF_Settings をセットします。

f:id:hiyokosabrey:20180218231046p:plain

ここでコンパイルするとエラーがでます。

f:id:hiyokosabrey:20180219094404p:plain

f:id:hiyokosabrey:20180219094801p:plain

同じ名前のカスタムイベントがいるためです。

そこで急いでイベントを入れ替えていきます。

いつものグラフで右クリックしてノードが検索できるやつで探すと出てくるので、つないであったカスタムイベントと入れ替えます。ちょっと見つけにくいけど、Add Event の中にいます。

f:id:hiyokosabrey:20180219093529p:plain

Add Event カテゴリにいるのは、Interfaceで関数に戻り値(Return Value)を設定しなかったのが理由ですが、UE4は戻り値がない関数はイベントとして扱われることがあります。頭に"Event" と付けられていますが、本当の名前には付いていないので名前が被ることになりました。

f:id:hiyokosabrey:20180219095702p:plain

↑この4つのカスタムイベントをいったん削除して付け替えます。 ↓

f:id:hiyokosabrey:20180219095738p:plain

これでコンパイルしてもエラーは出なくなります。

ちなみに、Interfaceで定義した関数はグラフに置けるのは1つだけなので、2つ目を置こうとすると、すでに置いてある場所にフォーカスが移ります。こういった事故を防ぐ仕様がステキですUE4

スライダーの改造をひと段落つけて、新しいWidgetを用意します。

 

テキストだけのWidget

f:id:hiyokosabrey:20180219101029p:plain

キャンバスには、スライダーと同じ大きさとカラーのテキストブロックを一つレイアウトします。

f:id:hiyokosabrey:20180219101225p:plain

is Variable にチェックを付けておきます。

フォーカス切り替えのアニメーションを付けておきます。

f:id:hiyokosabrey:20180219101920g:plain

グラフでスライダー同様にイベントノードにつなぐのですが、先に Interfaceを登録します。

f:id:hiyokosabrey:20180218231046p:plain

コンパイルしてエラーが出ないのを確認したら、Animationの再生ノードをつなぎます。

f:id:hiyokosabrey:20180219102325p:plain

このテキストだけのWidgetも汎用性を高くしたいので、初期設定用の関数を用意しておきます。

f:id:hiyokosabrey:20180219102554p:plain

テキストを受け取って差し替えるだけのシンプルな関数です。

これで完成です。

つぎは前回作った制御用のWidgetを編集します。

 

 

制御用Widget

 作ったテキストだけのWidgetをキャンバスに並べます。

f:id:hiyokosabrey:20180219112246p:plain

 

初期化している関数 を編集します。

まず配列変数周りをなくして、f:id:hiyokosabrey:20180219113427j:plain

テキストだけのWidgetに、ラベルのテキストを渡します。

f:id:hiyokosabrey:20180219112628p:plain

この関数の外にスライダーWidgetの数を保持する変数が待機しているので、そこに今回の項目数を戻り値として渡します。

 配列変数で処理するのをやめたのは、選択項目に別のWidgetが追加になって配列変数が使えなくなったためです。配列変数の型を wd_slider型 から UserWidget型 に変更しても、その配列変数には 1種類の同型のUserWidgetしか格納できませんでした。

2022/7/16 追記>>

あらんさん にご指摘(ブログ下部コメント参照)いただいて調べてみました。

記事を読み返してみて、前回の操作ですでに並べたWd_Slider型のオブジェクトから Promote to variable(変数に昇格) してる箇所があります。それを配列にしてるのでUserWidgetというカテゴリではありますが、VariableTypeが Wd_Slider型の配列になっているので、当然別のWd_TextOnly型が挿さらないわけです。当時の自分にツッコミに行きたい。

というわけで、Promote to variable せずに 新しくVariableTypeが UserWidget型の配列変数をつくるとエラーが出ずに、スルっと追加できます。

← ver4.27のキャプチャ

あらんさん ありがとうございます!

記事を書き直そうかと思ったのですが、差し替える必要のある画像が結構あって、しかも手元にあるUE4系は 4.27しかない状況。4.27でもプロジェクトファイルを開くことができました(この記事執筆時は4.18使用)が、アニメーションの挙動がおかしいのと、微妙にエディタのUIが変更になっているので、改めて UE5 で書き直そうと決意しました。便利なイベントも増えてますし。少し先になりますがなるべく近いうちにUE5版を公開します。

この記事を見つけて試していただいているのに失敗につき合っていただくのは心苦しいのですが、修正範囲が大きいのものあり、動かないわけではないのでこの記事はこのままにします。

<<

f:id:hiyokosabrey:20180219114844p:plain

そこで、前回は wd_slider型のWidgetしかなかったので、配列変数に格納できてそこから数を調べていましたが、今回は直接数を数えて返しています。

f:id:hiyokosabrey:20180219115439p:plain

ちょっと改造の手間を省こうとしてマジックナンバーで対応していますが、

プログラマに渋い顔をされてしまう場合は、親になっているキャンバスやその他パネルで余計なパーツが入らないようにしておけば、下のようなやり方もオススメです。

f:id:hiyokosabrey:20180219115856p:plain

 

ゲームに限らないと思いますが、UIを作るうえでのあるあるのひとつに、あとから項目の数が変更になるのが挙げられるとおもいます。すべてのノードをいつまでも把握しておくのは難しいので、あらかじめヒューマンエラーを起こさないように自動化しておくのはできるだけやっておいた方がいいです。

 

つぎに新しく、UserWidget型の変数をひとつ追加します。

f:id:hiyokosabrey:20180219121226p:plain

前回作った関数 "changeActiveWidget" を大改造します。

f:id:hiyokosabrey:20180219121620j:plain

↑これを ↓このようにします。

f:id:hiyokosabrey:20180219122241p:plain

ActiveWidgetという器(UserWidget型の変数)に、適宜該当するWidgetを入れていきます。

右端のフォーカスするイベントの呼び出しは、Interfaceで定義した関数にしないといけないので、検索して 作ったInterfaceカテゴリ探します。

f:id:hiyokosabrey:20180219122231p:plain

 

これが Interface の持つステキな仕様です。

なかなかピンとこないかもしれないですが、ActiveWidget に何か適当なWidgetが入っている状態だと仮定して、呼び出すための関数ノードをつなぐことができるのです。

普段、関数を呼び出す際には、呼びたい関数を持っていないとつなぐことができませんが、Interface 経由だと、関数を持っていなくても問題にならないのです。

 

あとは、wd_Slider型の ActiveSlider変数でつないでいるところを、入れ替えていきます。

f:id:hiyokosabrey:20180219173330p:plain

f:id:hiyokosabrey:20180219173408p:plain

後はここ↓

f:id:hiyokosabrey:20180219173605p:plain

 入れ替えてコンパイルに問題なければ完成です。

お役御免になった変数を削除します。

f:id:hiyokosabrey:20180219174506p:plain

確認してみましょう。

f:id:hiyokosabrey:20180219175121g:plain

フォーカスがいい感じに切り替われば成功です。

 

仕上げに、リセットのイベントを追加します。

f:id:hiyokosabrey:20180219180239p:plain

フォーカス用Index番号が 3 の時だけ受け付けるようにします。ちょっと雑ですが初期設定の関数をそのままつないで初期化として使ってます。

 

完全に初期化するか、変更前に戻すかは、決めておく必要がありますが、丁寧に作るならリセット用の関数を用意しておくと後から融通を効かせられます。スライダーWidgetの方にも指定した値に変更する関数があった方が便利です。

 

Index番号で判定する方法については、あとから項目の数が変わったり順番が入れ替わると、きちんと値を変えてやる必要があります。対策の方法はいくつかあると思いますが、今回はこれで。

 

レベルブループリント

リセットのイベントを呼ぶために、Inputノードを追加します。

f:id:hiyokosabrey:20180219181601p:plain

 

動かしてみます。

f:id:hiyokosabrey:20180219182011g:plain

いい感じになってきました。

 

いろんな種類のWidgetパーツを、InterfaceUserWidget型の変数 を使って、汎用的に処理する方法を紹介してみました。

 

長くなったので今回はこの辺にします。

ではでは ステキな設定初期化ライフを!

 

 

スライダーUIを並べて操作してみる

 

f:id:hiyokosabrey:20180210235447p:plain

前回 キーリピート処理を試すために作ったUIパーツのスライダーを並べてそれっぽく操作できるようにしてみようというのが今回の記事です。

 

limesode.hatenablog.com

 

まずは スライダーのWIdgetにパーツとアニメーションを追加します。追加するパーツは3つ。

項目名を示す「ラベル」と、「左右のキーを入力してね」と「いまこの項目を触ってるよ」という意味を持たせる一組の  <  > になります。

f:id:hiyokosabrey:20180211000308p:plain

f:id:hiyokosabrey:20180211000331p:plain

ラベル用のテキストブロックは、ブループリントから内容を書き換えるので、

Is Variableにチェックを付けます。あとの< > はブループリントからは直接触らないので画像等にしてもOK。

アニメーションは全部で4種類。

  • FOCUS ・・・ フォーカスされたとき
  • UNFOCUS ・・・ フォーカスが外れたとき
  • RIGHT ・・・ →右キー を入力したとき
  • LEFT ・・・ ←左キー を入力したとき

f:id:hiyokosabrey:20180211084832g:plain

左右のキーを入力したときのアニメーションは、ツマミが動くので、必ず必要ということはないですが、キー入力に対するリアクションは、分かりやすいほどユーザーフレンドリーなUIとなります。また、ユーザーは操作しながら無意識的にこのリアクションを記憶して学習していくので、「< > を見かけたら 左右入力できそう」というUI操作に対する期待感を育てることができます。これもひとつのUXです。デザインの段階で記号化のルール作りはとても重要になります。ここ試験に出ますよ(何のだ?)

 

Widgetブループリント

初期状態の値をもらう関数にラベルをセットする処理を追加します。

f:id:hiyokosabrey:20180211090404p:plain

Text型の引数(Inputsピン)を追加します。最後にスライダーの値更新用の関数をつないでいます。これは前回作ったやつで、処理の順番でおこる不具合対策でここに移動してきました。

というわけで、EventGraphが変わります。

前回↓のようになってたのを・・・

f:id:hiyokosabrey:20180211091022j:plain

こうします。

f:id:hiyokosabrey:20180211091436p:plain

ついでに左右キーを押したときに呼ばれるイベントなので、アニメーションの再生もここで行います。

 

続いてフォーカスとアンフォーカスのアニメーションを再生するイベントを新たに用意します。ただアニメーションをイベントとして再生するだけなのでカスタムイベントにつなぎます。

f:id:hiyokosabrey:20180211094506p:plain

f:id:hiyokosabrey:20180211094555p:plain

この2つの違いは、アニメーションの作り方によるものです。

UMGのアニメーションは、基本的にタイムラインの最後まできちんと再生しようとします。しかも同じ要素でのアニメーションがバッティングするとあとから再生したもので上書きされます。最終的に尺の長いアニメーションが勝ちます。

今回の4つのアニメーションでは、左右キー入力したときの LEFT と RIGHTのみ 0.2秒の尺で作りました。フォーカス切り替えでは、0.0 にキーを打っただけです。4つともカラーアニメーションです。

なので、左右キーを押して ”LEFT” か ”RIGHT” のアニメーションしている途中(0.2秒までの間)でフォーカスを切り替えると、一瞬だけ ”UNFOCUS” が再生されて残りの ”LEFT” か ”RIGHT” のアニメーションが再生されます。結果、”UNFOCUS” のアニメーションは敗北することになります。今のところ解決策は2つが考えられます。

  • 動いているであろうアニメーションを止める
  • アニメーションの要素がバッティングしないようにする

この挙動はバグにも思えますが、利用できる場面があるので、修正されないことを願っています。しくみが分かればきちんと対策できるので。(修正されるといろいろ面倒な処理が必要になる・・・)

このあたりの仕様を踏まえて、必要に応じてStopAnimationノードをつなぎます。

これでスライダーは完成です。次に並べて制御するためのWidgetアセットを新しく用意します。

 

 

 制御用Widget

f:id:hiyokosabrey:20180211105950p:plain

スライダーが一番マッチするサウンド設定の想定です。

キャンバスにバージョンアップしたスライダーWidgetを並べます。

f:id:hiyokosabrey:20180211104936p:plain

 

ブループリント

まずは準備する関数 "initSlders" を用意します。

f:id:hiyokosabrey:20180211105812p:plain

この関数を、EventPreConstructionにつないでコンパイルしてみると、

f:id:hiyokosabrey:20180211110258p:plain

キャンバスの内容が書き換わるのが確認できます。

 

引き続き関数を編集します。変数を2つ用意したいのでスライダーのWidgetノードから、Promote to Variable を2回します。

f:id:hiyokosabrey:20180211111307p:plain

作ったらすぐに消します。Variables のリストには残るので、リネームして一つは配列化します。

f:id:hiyokosabrey:20180211111803p:plain

この配列の方を関数に Set で戻します。そこに Make Array ノードをつないで、キャンバスに並べたWidgetを登録します。

f:id:hiyokosabrey:20180211112047p:plain

 仕上げに int型の戻り値(Outputsピン)に配列の登録した数をつないでこの関数は完成。

 

f:id:hiyokosabrey:20180211112722p:plain

 

 次に、int型の変数を2つ用意します。

配列に登録した3つのスライダーWidgetは、0~2の番号を使って扱うためと、スライダーの個数を保持しておくための変数です。

f:id:hiyokosabrey:20180211134356p:plain

先の関数からの戻り値を受け取るような形でつなぎます。

f:id:hiyokosabrey:20180211144806p:plain

 この続きには操作するスライダーWidgetを切り替える関数 "changeActiveWidget" を作って、

f:id:hiyokosabrey:20180211145409p:plain

くっつけます。

f:id:hiyokosabrey:20180211145615p:plain

 

あとは、前回のキーリピート処理を、レベルブループリントから持ってきます。

変数は移植できないので、ちょっと面倒ですが再び同じようにfloat型、TimerHandle型、Boolean型の変数をそれぞれ1つずつ用意しつつ、

f:id:hiyokosabrey:20180211150917p:plain

カスタムイベント "onKeyPress" を置いてつないでいきます。

f:id:hiyokosabrey:20180211151224p:plain

TimerHandle型は、Set Timer by Event のReturn Valueピンから Promote to Variable してもOK。

DoOnceノードのResetピンにつないでいた部分は、新たにカスタムイベントをつなぎます。

f:id:hiyokosabrey:20180211152032p:plain

 

前回のキー入力部分は、

f:id:hiyokosabrey:20180211152644j:plain

コンパクトにします。

f:id:hiyokosabrey:20180211152747p:plain

そして最後に、上下に並んだスライダーのフォーカスを順次切り替えるイベントを用意します。

f:id:hiyokosabrey:20180211153437p:plain

 上の2つのイベントは、←→左右キー用と、↑↓上下キー用になります。

それぞれの処理は上下と、左右で内容がほぼ同じなので、trueかfalseか、プラスかマイナスか、で分岐するようにして使い回せる形にしました。

このWidgetは一応完成です。

 

 

レベルブループリント

前回のレベルを改造するのであれば、Add to ViewportしていたWidgetが変わるので、前回 Promote to Variable していた変数が使い物にならなくなります。

f:id:hiyokosabrey:20180211154413p:plain

Input ノードで、↑ ↓ ← → のキー入力を検出して、それぞれのイベントを呼び出します。

f:id:hiyokosabrey:20180211154902p:plain

これで完成です。

再生して確認してみます。

f:id:hiyokosabrey:20180211155814g:plain

うまくいきました。

 

今回はこの辺で。それなりの操作ができるとこまでは来たかなと思います。

次回もうちょっとだけ手を入れます。

 

ではでは ステキなスライダーUIライフを!