みつまめ杏仁

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

スライダーUIを並べて操作してみる UE5版 続き2

前回の続き

基本の土台としてはそれなりにカタチになったと思うので、スライダー以外のUIパーツを作ってみようと思います。

今回の仕様はキーボードのカーソルキーで操作する想定にしています。

 

 

スライダーがUIパーツとして登場する画面にありそうなやつを 3種 選んで作ってみようと思います。

 

Index

 

 

スピンボックス

あらかじめ決められたいくつかの選択肢が、順番に切り替えられるタイプ。コンシューマーゲームが登場したころからメジャーになった印象がありますが、今でもよく見かける定番の設定用UIです。コンパクトでレイアウトにやさしく作りやすい。選択肢がテキストラベルで示されるので分かりやすいのがメリットだけど、選択肢の全体が見えないので、全部を確認するために一通り見たくなるというのがデメリット。これについては、なるべくループさせないのが良さそう。数と内容にもよるけど、ループしたことがわからないことが多く行き過ぎても気づかないことが結構ある。さらに選択肢が増えることを想定するのであれば、知らせるのが難しいのでこのUIはお勧めできない。

今回作るものは、選択肢の数をコッソリ忍ばせています。

 

wb_Slider をDuplicate(複製)すると使いまわせるパーツもあるし、関数やイベントの改造程度で済むのと、BPインターフェイスの登録も済んでるのでラクチンです。というわけで複製前提で書いていきます。

 

wb_Spin命名

 

Designer

パーツの構成は以下

 

こっそりと HorizontalBoxを置いています。中身は空っぽ。高さは 1px。

Is Variableを有効にします。

 

ヒエラルキーは以下

アニメーションはスライダー同様に用意します。

ただし、HorozontalBoxの中身は面積が小さいのもありますが、ちょっと作りがややこしい(動的に生成)ので、ズルしてHorizontalBox のBehaviorにある Render Opacity(透明度) で明暗を変化させています。

 

タイムラインのトラックにあるパーツをキャンバスおよびヒエラルキーから削除すると赤字になります。

グラフに置いていた場合はコンパイル時にエラーが出るので気づけますが、演出物やデコレーションパーツだった場合はコンパイルエラーが出ません。新しく同じ名前で作り直して同じプロパティ(設定項目)があれば、しれっと普通のカラーに戻ります。赤字のまま放置することができますが、復活しないのが分かった時点で削除してしまいましょう。

 

Graph

初期化関数 InitValue はちょっと大きくなります。

選択肢を テキスト型の配列 で受け取るようにします。選択肢の数を調べて変数にお取り置きします。

上の続きはこちら

右下の SetHighlightColor という関数はこうなっています。

フォーカス/アンフォーカスのカラーをきっちりセットするならここで行うとよさそうです。

 

値を更新する関数は以下

選択肢の数と同じだけループを回して、フォーカスしている番号と比較してカラーをスイッチ。

 

左右キーを押して内部の数値を切り替えるところで、範囲チェックしているマクロはこんな形にしました。

 

使ってる変数は以下

 

改造と追加は以上です。

 

組み込みは後述しますが、一足お先に動作の様子を貼っておきます。

 

 

 

 

レベル選択

これもコンパクトで段階やグレードの設定にむいてるタイプ。スライダーと原理的には同じで、段階が荒くざっくりと設定するときに使われる。表現としてはゲージと同じようなつくりでデザインの幅が広いのがうれしい。

今回 10段階で作成しています。0を含めているので 状態としては 11レベルあります。

 

さっそく中身を見てみましょう

アセット名は  wb_Level命名

 

Designer

パーツの構成は以下

テクスチャを用意します。サイズは変則で 36 x 48px

表示したい全体の幅を10分割して、圧縮とアライメント対策として 4の倍数になるよう調整しています。

このテクスチャをマテリアルでタイリングします。

マテリアルで描画することによって、ゲージとしての表現がすごくカンタンになります。

マテリアルを使わずにタイリングできますが、ゲージとして扱うにはそこそこ手数が必要なので、今回マテリアルで省力化しました。

UMG の Image WidgetはBrushのところで画像と同じようにマテリアルをセットすることができます。

 

ヒエラルキーは以下

 

 

Graph

マテリアルの中に干渉するために、Dynamic Material Instanceを作っておきます。

Promote to Variable(変数に昇格)すると手間が省けます。

 

値を更新する関数で利用します。

 

初期化の関数はスライダーと同じなのでそのままで。

 

 

範囲チェックのマクロはループなしです。

 

今回使った変数は以下

 

改造と追加は以上です。

 

組み込みは後述しますが、一足お先に動作の様子を貼っておきます。



 

 

 

チェックボックス

スピンボックスで代用が可能なのと、今回他のタイプに合わせてコンパクトに作ったので、選択肢が少ないのが残念ではある。On/Off や True/False みたいな対義語ではなく、2つ並べないと比較できないような選択肢で効果的だと思う。

チェックボックスな見た目だけど、複数選択できないのでラジオボタンと同じふるまいをします。そういえば 近頃は「ラジオボタン」ってどれくらい通用するんだろうか。

基本の仕組みがあれば、いろいろアレンジできるよという例として見てもらえれば。

 

アセット名は wb_Checkbox命名

Designer

パーツの構成は以下

チェックボックスはテクスチャとマテリアルを使って見た目をスイッチします。

サイズは 128 x 64 px Grayscale

 

パーツの各サイズは

40 x 40 px

 

これをマテリアルで切り出します。

40 px 横に移動させると絵が変わります。2パターンしかないので、パラメータを 0 か 1に限定して扱うようにすると、 移動幅(この場合 40/128 = 0.3125)に掛け算することでスイッチとして機能するようになります。

 

 

ヒエラルキーは以下

 

Graph

マテリアルのパラメータをいじるために、Dynamic Material Instance を準備。

 

初期化の関数はこんな感じに

選択肢が 2択なので、Integer型だった変数 Value は Boolean型にタイプをチェンジして受け取り。

選択肢用のテキストラベルは数が固定なので、配列で受け取ってそのまま表示しに行きます。

 

値を更新する関数はこんな感じ。

マテリアルのパラメータをスイッチするだけの簡単なお仕事。

 

範囲チェックのマクロはループなしの場合

 

ループありの場合

ブールの値は、NOTノードを使うと否定されて反転することになるので、それを自身に代入することで トグルスイッチ として利用します。

 

今回使用した変数は以下

 

改造と追加は以上です

 

組み込みはこのすぐ後に続きますが、一足お先に動作の様子を貼っておきます。

 

 

 

組み込む

さてさていよいよ大詰め。先に作ったスライダー達と一緒に並べていきます。

前回作った wb_Settings を編集します。

 

Designer

はい、並べました。

ヒエラルキーはこうなりました

順番の入れ替えやら増えたり減ったりすることを思うと、このネーミングはよろしくないのですが、この後の配列に登録する場面では便利になるはず。

 

Graph

初期化のところで配列に追加します。

このグラフの後ろで、テキストラベル(表示名)と初期値をセットするのを追加します。テキストや数値、選択肢の量などは自由に変えてみてください。

 

以上で追加完了です。

カンタンですね。

あとはコンパイルして問題なく動作すれば完成。

 

動いてるのはツイッターに貼ります。

 

最後に

いかがでしたか?

設定画面としての完成は目指していないので、中途半端な終わり方かもしれないですね。ゲームのデータをどう反映し、またフィードバックするかはシステムを設計される方にお任せします。

ブループリントインターフェイスを使うと関数を共通化できて UIのパーツを派生させて制御するのが易しくなります。4年前の記事は一度できたものを修正するという構成だったので、今回は最初からBPインターフェイスを用意する流れに変えました。

UE5版でリライトのために読み直しましたが、昔の自分だけど知らない人の記事を読んでる感覚にもなって不思議な気分でした。

他の記事でもUE5版にして欲しいものがありましたら、コメント欄からどうぞ。

ぼちぼちの更新になりますが、できる限り対応していきたいと思います。

 

ではでは

今回はこの辺で

ステキなUIデザインライフを!

 

 

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

前回の続き

 

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

キーリピートの処理が無事動かすことができました。

以前の記事だと、UIパーツとして整えていくところですが、順番を入れ替えてここでブループリントインターフェイスを用意するところから始めていきます。

 

 

Blueprint Interface

ブループリントインターフェイスは独立したアセットになります。

コンテンツブラウザで右クリック > Blueprints > Blueprint Interface を選択

プロジェクト内でユニークに扱われるので慎重に命名します。

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

編集ウィンドウを開くと、すでに 1つ作られていて、関数名を決めてほしそうに待機してます。気が早い。

関数の追加はFUNCTIONSの右端にある ⊕ボタンから。

BPインターフェイスでは関数の名前と入出力、その他設定だけの登録になります。

エディタのグラフに READ-ONLY とあるように関数の中身自体はここでは空っぽのままです。

今回は、イベントとして機能させればいいので、追加と命名だけでOK。

フォーカス状態が切りわったときの Focus Unfocus、左右キー入力時の Increment Decrement の 4つを用意します。

用意できたら保存して閉じます。

 

 

 

前回作ったWidgetブループリント wb_Slider を編集していきます。

 

複数のスライダーを並べた状態では、どのスライダーが操作対象か分かるようにしないといけません。

 

目指すイメージ

 

前回から追加したい部品は 2種類

  • 項目名を示す「ラベルテキスト」
  • キー入力の方向をなんとなく示す「<」と「>」の記号

 

そして必要になる演出(アニメーション)は 2種類

  • スライダーが操作対象であることを表す表現
  • キー入力を受け付けたことを表す表現

 

 

Designer

手間を省くために今回「<」と「>」は文字で表現することにしました。 演出用のパーツなので画像であっても問題なく進められます。

追加したのは 3つの TextBlock

ラベル用のTextBlockは、ブループリントから書き換えたいので、Is Variable を有効にします。

 

アニメーションを用意します。 まずは 4種類あればOK。

左右のキー入力で値の増減、上下のキー入力でフォーカスを切り替える想定。

  • FOCUS ・・・ フォーカスされたとき
  • UNFOCUS ・・・ フォーカスが外れた時
  • RIGHT_PRESSED ・・・ →右キーが押されたとき
  • LEFT_PRESSED ・・・ ←左キーが押されたとき

左右キーの入力については、数値とツマミが変動するので、必須というわけではないですが、操作に対してレスポンスがあるというのは、ユーザーとって手応えになるので、丁寧なつくりを目指すならあるとうれしいですね。こういうのをマイクロインタラクションとも言います。操作とそれに沿った動きを見せることで、記号と効果を強く紐づけることが期待できます。学習コストを下げるのを狙うのであれば、まさにこういったところにこだわるのは大事です。

 

アニメーションができたら次はブループリント

 

Graph

先に用意しておいた ブループリントインターフェイスを登録します。

ヘッダーメニューの Class Settings ボタンをクリック。

左下にあるDetailsタブから、Interfacesの項目を探して Addボタン(なぜかプルダウンな見た目)を押して、IF_SettingItem を探して選択すると登録完了。

登録されると、My Blueprintのタブに、INTERFACES が追加されます。

これをグラフに取り出すとイベントノードとして扱うことができます。

ドラッグ&ドロップはできない仕様です。

試しに、Incrementをグラフにドラッグ&ドロップしてみるとこんな警告がでます。

グラフへの取り出し方は 2つ。

一つはリストから右クリックして、Implement Eventする。

もう一つは、グラフ上で右クリックして見つける方法。

頭に"Event" が付けられるので、見つけにくいですが Add Event カテゴリに追加されています。

グラフに取り出すとこんな見た目のノードになります。

さっそく前回作ったカスタムイベントと入れ替えます。

 

ちなみに既に同じ名前の関数およびイベントが存在するとコンパイルエラーになります。

今回エラー回避のために被らないように命名してもよかったのですが、BPインターフェイスの方がプロジェクト内でグローバルな存在になるので、ローカルな存在のカスタムイベントに命名を譲るのはちょっと負けた気がしたので、わざと被らせました。キーリピートの仕組み作ってるときに対策できたんですが、わりと遭遇しやすいエラーなので、事例として紹介しておこうという魂胆です。

 

入れ替えついでに、左右キーを押して値が増減する時にリアクションするアニメーションをつなぎます。

4年前と違うのは、マクロの後ろに持ってきたところ。

今回はループするので、特に違いは出ないのですが、何らかの制限や条件があってアニメーションにも影響させるとなると、この順番のほうが都合がよさそうだからです。

 

たとえば値が端までいってもループしないとなると、マクロ内で更新しない方へ分岐できます。

値の増減で範囲を越えると値を更新せず抜けるようにOutputにピンを増やす。

 

そこから、これ以上は無理ですよのアニメーションを再生するようにつなぐと出来上がり。

実行される順番が分かりやすく、改造しやすいのがビジュアルスクリプティングならではだと思うのです。

 

 

続いて、スライダーがフォーカスされた時と解除された時のイベントを用意します。BPインターフェイスのイベントを利用します。

左右のキー入力時に、0.15秒のアニメーションをつけているので、アンフォーカスのイベントだけ、先にStopAnimationノードで止めています。今回作ったフォーカスとアンフォーカスのアニメーションが左右のキー入力アニメーションより短いので、残っていた場合に現れてしまうのを防ぐためです。

フォーカスする場合、別のスライダーWidgetにフォーカスすることになり、そこはすでにアンフォーカスの処理が済んでいる前提です。

 

これで、イベントの用意が全て整いました。

最後に初期値をもらう関数にノードを追加します。値と一緒にラベルテキストも受け取ります。

前回の記事で Event Construct に Update Value関数をつなぎましたが、↑ ここに移動させます。

Viewportに追加した際に、Event Construct が先に実行されてしまうので、UpdateValue関数の処理がすでに終わってから、この Init Value関数が呼び出されることになり、ツマミだけが反映されないことになります。なので値を受け取ったタイミングで確実に更新させられるようになります。

その代わりに、ここで アンフォーカスのイベントを呼び出すようにします。

My Blueprintタブの GRAPHSカテゴリにある EventGraphからドラッグ&ドロップします。

ノードの左にある Targetピンの色に注目。

 

これで画面表示開始時にアンフォーカスの状態で始まるようになります。

キャンバスに置いたパーツのデフォルト状態(エディタで何のアニメーションも適用していない状態)がアンフォーカスと同じになっていれば、このイベントを呼ぶ必要がなくなるのですが、アニメーションの調整作業していると、うっかりデフォルト状態に戻し忘れていることがあるので、保険的な意味合いです。

 

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

 

 

次に並べるためのレイアウト用Widgetを新しく作ります。

wb_Settings 命名

 

さっそくスライダーWidgetをキャンバスに並べます。

 

Designer

Paletteタブの USER CREATEDカテゴリから wb_Slider を探して配置します。

ひとまず縦方向に 3つ並べました。後からまとめて移動できて等間隔に並べるのが楽なVerticalBoxを利用しました。

キャンバスにドロップするとWidget名の後ろに自動的に番号が振られるので、上から順番に 1st , 2nd , 3rd にリネームしました。

 

レイアウトができたら、グラフを編集していきます。

 

Graph

まずは変数を 4つ追加

Integer型の変数 2種

focusIndex ・・・ 操作対象のスライダーを番号管理するためのもの

MaxItemCount ・・・ 操作対象を切り替えるとき、ループさせるのに使う

 

User Widget型の変数 2種

activeWidget ・・・ 操作対象のスライダーにアクセスするために使う

Items ・・・ レイアウトしたスライダーWidgetを格納するための配列

 

初期化の関数を用意します。

関数名は InitItems としました。

作っておいた User Widget型の配列 Items にキャンバスにレイアウトしたスライダーを上から順番に格納。配列の要素数を Lengthノードで調べて MaxItemCountに代入しています。そのあとで各スライダーの初期値とラベルテキストをセットしています。

これも 以前のと逆にしています。処理順はどちらでも特に有利不利はないと思います。ただ、こちらのほうが後々いろいろ追加があったときに編集しやすいと思ったのが理由。

User Widget型の変数は、Widgetブループリントを作るときに選ぶやつです。

基本的にこのクラスを親として子孫を作ることになるので、User Widget型の変数にはWidgetブループリントが格納できます。今まで拒否られたことがないのですが、フツーに作っている分には便利に利用できます。

 

つぎに、スライダーのフォーカスをセットする関数を用意します。

changeActiveItem と命名

 

用意した 2つの関数を Event Construct につないで、最初にフォーカスするスライダーをセットします。

Integer型の変数 focusIndex を初期化の関数に入れても問題ないです。今回入れなかったのは、状況によってはスタート時のフォーカス位置が可変することもあるから、というのが理由ですが、あまり強い理由ではないです。

 

操作対象のフォーカスを切り替えるためのカスタムイベントを2つ用意します。

これらは上下キーを押したときに呼び出されます。

切り替える前に、現在フォーカスしているのをアンフォーカスします。そのあとで focusIndex のカウントアップ・ダウンさせてループ処理を入れます。プラスの方向は%(剰余)が 0 → 1 → 2 → 0 → 1 → 2 → 0  ... と便利なんですが、マイナスの方向は 0 → -1 → -2 → 0 → -1 → -2 → 0 ... となってしまい、配列に使うとエラーが出ます。ブランチノードは使わず Selectノードを使ってループさせています。

左右入力の部分は、キーリピートのテストで作ったやつを、レベルブループリントから移植したいのですが変数は持ってこれなかったりコンパクトにしたりするので、慣れるためにも もう一度構成しなおします。

 

思い出の一枚

 

これをこうします。

左右キーの部分は、Inputノードから キーを押したときと離したときの 2系統を用意する必要があります、押したときはすでにある onKeyPressを利用し、離したときに相当するカスタムイベントは新しく追加しています。上図 onKeyRelease

 

増やした変数は 3つ。

 

キーリピートの間隔を初期化するところが必要

この部分は新しくカスタムイベントを用意して対応。

ついでに、 LeftとRight で分岐していた部分は あとの Boolean型の引数を受け取る形でまとめてしまいます。

onChangeValue と命名

これで準備完了。

外部から呼ばれるイベントは 4つ

  • onChangeValue ・・・ 左右キーを押したとき
  • onKeyRelesase ・・・ 左右キーから指を離したとき
  • Next ・・・ 下キーを押したとき
  • Previous ・・・ 上キーを押したとき

 

最後はレベルブループリントを整えます。

 

Level Blueprint

Viewportに書き出していたWidgetが変更になります。

スライダー単品をレイアウト用のWidgetに変えて、変数化していた wb_Slider も使えなくなるので作り変えます。

 

キー入力部分はこんなにシンプルに。

 

これで今回は完成です。

テストしてみましょう。

うまくいってるようです。

ということで今回はこの辺で。

次回は、スライダー以外のWidgetを作って追加してみようと思います。

ではでは

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

 

 

補足

User Widget型の変数にWidgetを入れて使う場合、いろんなWidgetを格納できて便利なんですが、扱い方に ひと手間必要になります。

直接アクセスする場合はWidgetの持つ関数やイベントにアクセスする際、 call で検索するとリストアップされます。※Editor Language が Englishに設定されている場合

User Widget型の場合、User Widget型で間違いはないけど具体的なWidgetが特定できないのでリストアップされない。

そこで、特定するためにキャストノードをつなぎます。

今回はスライダーしか扱っていないですが、いくつかのWidgetミックスするためにUser Widget型を使う場合、このキャストノードを使った解決は、いちいち特定する手数が必要になります。そこで大変相性がいいのが、ブループリントインターフェイス。次回の記事でその辺の恩恵が実感できると思います。

 

 

 

 

 

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

時は四年前。 2018年の2月に公開した内容で、間違いに気づかず、問題を避けるかたちで解決したことにしている部分があって、その雪辱戦といいましょうか、修正するにも当時のバージョンはすでになく、空きのないドライブと格闘してスクショ撮るのも大変そうなので、UE5版としてリニューアルすることにしました。配列変数の作り方を書いてるのはよかったのですが、既存のWidgetから昇格して作ったので、違うWidgetが追加できるわけもなく、当時の自分はこのミスに気づいてなくて、先日コメントでご指摘いただきました。今更ながら恥ずかしい限りです。

 

該当する一連の記事はこちらになります

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

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

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

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

スピンボックスも作ってみた - みつまめ杏仁

 

結構な量書いてるな・・・。

4年越しでコピペするのは面白くないし、伝わりにくそうなとこを補間しながら、なるべくコンパクトを目指しつつ、UE5の差分とかで気になるものがあれば書いていこうと思います。

変数名やオブジェクト名、アセット名など一部名称を変更しているものがあります。

 

 

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

この機能を作ったところから始まったのでここから始めます。

まず Widgetブループリントを一つ作成。

 

コンテンツブラウザで右クリック > User InterfaceWidget Blueprint を選択

 

UE5 ではこんなポップアップが出るようになりました。

ここで同プロジェクト内で既に作った Widget ブループリントを親クラスとして選択できるようになっているので、開発の効率化を意識したフローになっているのはいいですね。

新しいものを作るので、Commonのところの User Widget ボタンを押すとアセットが現れます。

これに名前を付けて編集していきます。今回 wb_Slider と名付けて進めていきます。

 

Designer

エディタを開いた時、最初に置かれているのが Overlayだった場合

右クリックして、 Replace With... > Canvas Panel を選択すると入れ替えることができます。

Overlayで進めることもできるのですが、テキストを右詰めにしたかった(Overlayだとちょっと調整しにくい)のと、それぞれのパーツの位置関係を絶対値として扱いたかったのでCanvasPanelを選択しています。Overlayの下にCanvasPanel置けばええんやないの? という声が聞こえてきそうですが、階層構造が深くなると、その分レイアウトに必要な計算量が増えるます。できるだけ浅く作りたいものです。

 

この初期配置のWidgetは、

Edit > Project Settings > Editor > Widget Designer(team)  > Desinger > Default Root Widget

で変更できます。

 

キャンバスに Image を 2つと TextBlock を1つ配置します。

レイアウトはこのような配置。

右端がMAXの想定なので、ツマミ(Image_Knob)は左端に配置。

ブループリントから触るための Is Variable スイッチは、Image はデフォルトで有効になっていますが、TextBlock は無効なので有効にします。

 

パーツの配置が終わったのでグラフのほうを編集していきます。

 

Graph

変数を2つ用意します。

UE5になって変数の型が明示されるようになったのはいいですね。配信やスクショに配慮ということなのかな。

変数 MaxPos にツマミの移動量を入れておくために、Image_Base のサイズを調べます。

Event Pre Constructにつなぐと、コンパイルの時点で情報を取得することができるようです。

GetSize ノードの ReturnValue ピンは、濃い青色になっています。これは複数のピンが束ねられている状態(構造体)なので、バラす(Split)ことができます。

ピンの上で右クリックして Split Struct Pinを選択。

Breakノードを使わずにつなぐことができます。

 

デザイン的にスライダーの長さが確定するまでは、このパーツの長さを調べて代入するという接続が無難です。確定してもう変更しないとなれば、変数 MaxPos に初期値をセットしておけば、この調べるという処理は省略できます。

 

ちなみに Overlayで作る場合、サイズの取得方法が変わります。

Image Widget が Brush 情報として持っているのでそれを拾います。

CanvasPanelの場合、このBrush情報とは別に描画するサイズを指定できてしまいます。テクスチャ由来のサイズを基本とするならOverlay同様、Brushから取得するのが賢明です。

BrushでImageSizeを指定して、CanvasSlotでは Size To Contentを必ず有効にする。という方針を立てて開発するとよいかもしれません。

OverlayとCanvasPanelの混成する状況でもややこしくなくていいかも。

 

 

関数を2つ用意します。

ひとつはツマミを指定した位置に移動させ、数値を更新する処理。

便利な Lerpノードを使います。A と B につないだ 2つの値について、Alphaにつないだ割合(%)に応じてブレンドされた結果が取り出せます。活躍する場面が非常に多くて便利なので大変重宝します。

 

Integer型(整数)の割り算は少数以下を切り捨ててしまうので、先にFloat型(浮動小数)に変換します。

 

 

もう一つの関数は、外部から値をもらう関数です。

関数名に初期化をイメージする命名をすることで、値の使われ方を示す狙いがあります。このInteger型の Value という変数は、念のため Private に チェックをつけておくと、不用意に外からの書き換えを防げるので安全です。

 

つぎに、値を増減させるためのマクロを用意します。

受け取った値 +1-1 を 変数 Value に加算して、 0~100の範囲を越えないようにします。%ノードは 割った余り(剰余)を計算してくれるノード。直前に加算しているのでValueが 100 の時に +1されて101になり、それを 101で割った余りを求めると 0 になるので、100 の次は 0 になります。Valueが 0 のときに-1 を足すと 0以下になるので、Branchノードで判定してValueを 100 にします。

%ノードは値を循環させたい場合にとても重宝します。値がマイナスにならないのであれば判定部分は省略できます。

 

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

Event Construct に 値を反映する関数 UpdateValueをつないで、あとはカスタムイベントを2つ追加します。

名前を Increment と Decrement としました。それぞれにマクロをつないで、結果を UpdateValue関数につないで完成です。

 

キー入力を処理する外部のブループリントから、このカスタムイベントを呼び出します。

 

 

Level Blueprint

レベルブループリント編集を開始する方法がUE5のUI変更にともなって変わりましたね。コンテンツブラウザでレベルブループリントのアセットアイコンをダブルクリックしてもシーンが開くだけでブループリントの編集ができないのですよね。

このレベルを開いている状態でヘッダーメニューから Open Level Blueprintを選択。

 

 

Create Widget ノードからの Add to Viewport は Widgetを表示するための定番コンボ。

ここで wb_Slider を召喚します。後から利用するために、変数に昇格しておきます。

そこから関数を呼び出して、スライダーのツマミのスタート位置である初期値を渡します。

試しにコンパイルしてエラーが出ないのを確認して再生します。

関数に渡す Valueの値を変えてみてきちんと反映されていればOK。

 

キーリピート処理を作っていきます。

まず 新しく変数を2つ追加。

Float型とBoolean型。

3つめの青い Timer Handle型の変数はこの後のタイマーノードから作るとラクです。

 

カスタムイベントを1つ追加します。

そこへ Set Timer by Event ノードを取り出してつないでいきます。

このカスタムイベントと、Set Timer by Event ノードのコンビネーションは、もう黄金コンビ(古い?)ベストカップル(これも古い?)ゴハン何杯でもいけます。Event Tickを使わずに一定のタイミングでループ処理を作ることができます。

しかも任意のタイミングで、動かしたり止めたりができるので、無駄に動き続けるようなことはありません。

Set Timer by Event ノードは、指定した時間がきたら、左側の角丸のピンでつながった先のイベントを実行します。Delayノードと違うのは、あくまでもタイマーのスイッチを入れるノードなので、普通に後ろにつながったノードは実行されてゆきます。

今回のキーリピート処理では、初回だけ待機時間を長めにとって、2回目からは短くすることで、狙った動きにすることができます。

その 2回目以降の間隔を設定するために Do Once ノードをつなぎます。

リピートのために間隔を短くした値を Float型の変数に入れます。
とりあえず 0.025 という値を入れています。 単位は 秒です。

通常ゲーム画面は高速で絵を描きまくっているため動いて見えます。TVモニターの技術的な都合もあって、1秒間に60回の描画がベスト、とされている時代が長く続きました。フレームパーセカンド(=fps)を使って表記すると、 60fpsとなります。計算量が多く負荷の高いビジュアルを作ったり、データ量の多いアセットを扱うと、あっという間に60fpsを維持できなくなります。よくカクつくという表現で言われたりするあれです。

最近は単純にハードウェアのスペックが上がってて、伝送量が増えたりして伝送速度が上がったりHDMIの規格が増えたり、HMDの普及もあってより高速なフレームレートに対応できるようになってきました。とはいえ、ゲームでこの60fpsを維持するのはめちゃくちゃ難しいので60出てたら凄いってなります。

1秒間に60回ということは、画面を1回描ききるのに 1/60 で 約 0.016666...秒かかります。

なので、0.016秒より短い間隔にすると変更が目に見えないことがあるので、もろもろの処理負荷を減らす意味でも短くしすぎないようにするのは大事です。

リピート間隔を調整するための、指標みたいなものがあったほうが決めやすいかと思って長々と書いてみました。

 

あと少し

キー入力処理の部分。Input系 ノードを使います。

これは、キーボードやタッチパネル、マウスやゲームパッドなどの入力デバイスからイベントとして情報を受け取るためのノードです。

簡単にキーボード操作にするなら、Keyboard Eventsカテゴリの Left と Right ノードが便利。

 

カーソルキーの左右を押すたびにスライダーの値を更新したいので、下のようにつなぎます。

キーを押した瞬間だけこのInputイベントの Pressed が呼ばれ実行されます。

指を離すと Released が呼ばれ実行されます。

これで押した瞬間にタイマーをセットして指を離すとタイマーを解除(クリア)という流れになります。

指を離したときに、次回のために Do Onceノードをリセットする必要があります。

そこで Clear and Invalidate Timer by Handle ノードでタイマーをクリアした後に DoOnceノードにReset ピントつなぎます。

これで準備が整いました。

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

 

 

そういえば、最近はカーソルキーって言わないのかな?方向キー?矢印キー?

左右の矢印を変換するときに を入力して変換すると  が出てくるのを知ってからはよく使うようになりました。

以前は 「ひだり」と入力して「←」に変換してたんだけど、IMEが学習してしまい「ひだりうえ」を変換すると 「←うえ」みたいなことになってのが面倒で・・・

 

初回の少し長めの待機時間がなぜ必要か、というのが気になったら初回の待機時間を短くしてみることをおすすめします。

2か所の 0.75 のどちらか一方をリピートと同じ時間(今回の記事では 0.025)にしてみると効果が判りやすくなります。キーを押して離すまでに結構時間がかかっていることに気づくと思います。

 

次回より UI らしく複数のスライダーを並べて操作できるようにしてみようと思います。

 

ではでは

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

 

雑記#20220718

夜帰宅中、歩いていると聞きなれない音に気付いた、壊れた電子ブザーみたいな音で、長く一定のトーンで聞こえてくる音。まだ蛙の声も聞こえる時期なので秋の虫も少ないせいか際立って聞こえてくる。そういえばどうぶつの森で聞いたことがあるような・・・調べてみたらオケラだった。結構長くこの道歩いてるけど気にしたことなかったな。確か土のある所に暮らしているはずだけど、田んぼ付近はともかく、マンションと路地との隙間から聞こえてきたりする。最初は耳鳴りを疑ってしまった。

さてさて

別にカードゲームを作りたかったわけではなかったのだけど、先日雀魂(じゃんたま)を遊んでいて、牌の上をマウスカーソルが乗るとピコっと牌が少しだけ飛び出るフォーカス処理、あれを作ってみたくなって、UMGで試してました。

ただ横に並べるだけだとつまらないので、カードゲームの手札みたいに扇っぽくできないかな、ということでカードになりました。

試してみたこと2つ

  • HorizontalBoxで扇状に並べることは可能か?
  • HorizontalBox内のアイテムは優先順位は変えられるか?

過去に何度か触って答えはわかっているものの、バージョンが変わればひょっとしたら・・・みたいな期待感は常にあるので思いたったらとりあえず試す流れで。

 

ここからの内容は、見出しを付けていますが、つながりは弱いので気なる見出しだけ拾い読みしてもいいようにしています。

 

 

 

やってみた結果

まずは重ねて角度をつけてみる。

 

ここからいい感じになるように計算しつつ並べてみたのがこれ。

 

並べるカードはただ画像を並べるのではなく、別のWidgetでマウスイベントを仕込んであるのを並べています。

マウスカーソルが入るとぴょこっと上に動いて、カーソルが離れると元の位置に戻るアニメーションを用意しているので、並べるだけで作ってみたかったフォーカスの動きが完成。

ここまで作って終わるのがさみしくなって思いついたのが、スポットライトみたいな表現。

 

 

スポットライトみたいな表現

最近の個人的な流行りが、描画する画面内の位置をUV座標として扱う表現。

UIは、表示するパーツを画面内に配置するとき、遷移演出やインタラクティブに変化するものとしないものがあるので、用途ごとにデザインを部品として切り出して配置します。それぞれの部品は独立したものとして扱うことになるのがフツーで、連動してるように見せるのはダイナミックな演出が期待できる分、仕込むのにそこそこ手間がかかるのです。そこで活躍するのが、ScreenPositionを使った表現。

アニメでキャラクターが一瞬チラっと見える小さなナニカに気づいて注目する演出とか一人称視点になってスローモーションや静止画になったりモノローグで思考が語られたりするあれ。

そういえば最近『ラブレター』というカードゲームで遊んでるんですが、面白いですね。ヨミアイが熱いゲームは好きです。

 

Size: 256x256 px

このテクスチャをマテリアル内でMultiply(乗算)しています。

乗算を選択したのは、カードのカラーに対して輝度を下げることになり絵柄の情報を維持できるからです。加算した方が光を当てた表現に近くなりますが、当たっている場所のカラーが明るくなってディティールが失われやすい。カードのそもそもの輝度を下げて暗くしておいてから加算することで対策できますが、周囲を落とす方が中心もしっかり見せられるし、調整も簡単なので 乗算 というわけです。

テククスチャが256x256という小さな正方形なので、サイズ補正用の値をScreenPositionに掛けています。このせいで後から苦労するはめになります。

 

タイリングはしない設定(テクスチャのインポート設定で変更可能)なので、テクスチャの外側が無限に続く見え方になります。

ScreenPositionに対して、オフセット位置を足せば見た目に移動させることができます。マウスカーソルがカードに乗っている間だけカーソル位置に合わせればできあがり。

先に書いたようにスポットライトにしたかったわけではなかったのですが、円の周辺に補色を入れてみたらいい感じに色味が増えて光の表現ぽくなったので、面白いから採用することにしました。

 

 

マウスカーソルの位置を反映

これがなかなか難物でした。

マウスカーソルの位置をとってくるのは、onMouseMove関数を用意(MyBlueprintタブのFUNCTIONSからOverrideして作成)して、その中で下のようにつないでます。

この関数は名前を見る限りはマウスの動きを検出して実行されると思うですが、マウスに触れていなくても常時実行され続けるので変数に保存した値と差分が出たら実行するように分岐を入れています。

エディタ実行で確認すると若干誤差が出ますが、Standaloneで実行すると誤差は出ないのでひとまずこれで進めました。(2K解像度で 0.012くらいの補正を入れると目視でいい感じになる)

取得したマウスカーソルの位置を解像度で割ると、0~1.0の値になるので、Lerpノードを使って補正値を算出。その値をマテリアルパラメータコレクションに書き込みます。

テクスチャにスケールをかけない場合(Tiling=1.0)はカーソル位置とテクスチャのオフセット位置の関係は以下のようになります。

 

ここにスケール 3.2 : 2.0 をかけた場合こういった値になる。

+0.5した場所から、最大位置まではスケールと同じ数ということになる。

つまるところ、テクスチャの真ん中を画面の左上に持っていく補正(+0.5)が必要なだけで、あとは単純にタイリングのスケール分でよかったという事実。

 

UV空間ってスケールがかかるとイメージがしにくい(個人的な感想)ので上の画像のように理解して腑に落ちるまで、擦った揉んだしてしまいました。

 

 

 

スポット表現の移動はマテリアルパラメーターコレクションを使う

カードは一枚ごとにマテリアルを使ってテクスチャを描いています。

マウスイベントを受け取ったら複数のカードに、スポット表現の移動を反映しないといけないのは効率が悪い。そこでマテリアルパラメータコレクション(以降MPC)アセットを使うことにしました。

ブループリントからこのMPCに値を書き込むことで、カード個々のマテリアルはMPCの値を参照するようにしておけば勝手にそれぞれが反映するかたちになります。

MPCの値を受け取ってるマテリアルはMPCの影響を常に受けるのです。

 

ブループリントからMPCへ値を書き込むのが Set Vector Parameter Value ノード。

Set Scalar Parameter Valueも用意されています。

 

ブループリントって、たいてい操作対象に対してSetやGetをするので、ついついこのノードを使うときも先に変数を作っていました。

するとパラメータネームの部分がプルダウンリストになっているのですが、選択できないのです。

Collectionピンに変数を挿すとコレクションに設定したパラメータが選択できなくなる仕様。Name型の変数にパラーメータ名を入れてつなぐと解決はしますが・・・

 

何もつながずに、コレクションをセットすると、パラメータネームをプルダウンで選択できるようになります。

変数が要らなくなりました。

Tonkotsuさん(@tonkotsu3656)に教えていただきました。ありがとうございます。

 

 

 

 

カードのテクスチャの節約を考える

カードの絵柄を考えたとき、重要な情報はカードの大きさよりいくらか内側に小さくて、余白があるのがほとんどだと思う。そこで、カード一枚分を単体のテクスチャにして、絵柄は別のテクスチャにして詰める。

カードのテクスチャサイズは画面での表示サイズを考えて 192x288px に決定。

絵柄を切り抜くためのマスクも一緒に作成。

 

トランプの場合ジョーカーを除く52枚が必要。

カードの大きさ 192x288 をそのままテクスチャにすると、べき乗に美しく収まらないうえに、2048x2048px のサイズが必要になる。

余白が結構出るので、ここに裏(数字の書いてない方)のデザインバリエーションを仕込んだりジョーカー置いたりできます。

うまく収めるために、カードのサイズを見直してもいいのですが、UVの切り出しや圧縮を考えると奇数は出したくないし、こんなテクスチャ都合で、画面のデザインを変更するのは避けたいものです。そこで絵柄をミニマムに切り詰めて並べるとこうなりました。

2048x1024px です。半分に抑えられました。カードのベースとマスクを入れても2048x2048よりは全然ましです。

普段UIを実装する際はいつもこういったテクスチャのサイズと格闘しています。いかに効率よく最大数を得られるか、を検証し交渉材料にします。

例えばプランナーから「80種類もあったら大丈夫ですよ。足ります」と言われたら、僕は96枚くらい入るよう頑張ります。多すぎはよくないですが、ギリギリもモチベが下がるので、上にあげた例のように想定の範囲+αが出る程度にバッファを意識するとあの名セリフを吐くことができます。「こんなこともあろうかと」そして「そのかわりもうこれが限界」を合わせて言うと職人的信用度もあがるし貸しも作れます。

 

絵柄は一つにつき 144x256px

実はさっき書いたことと早速矛盾しますが、うまく収まるサイズを計算して調整しました。

マテリアル内で絵柄とベースを合成するのはこのようになりました。

 

途中ふと、トランプには重ねて持った時でもマークと数字が見えるようにデザインされているのを思い出した。せっかく余白を開けて絵柄を効率よくテクスチャアトラスにできても、これではトランプゲームは作れない。

そこで絵柄をカードのマテリアルで合成するのではなく、別々のパーツにして自由に配置できるようにしたほうがよくないか?という考えに至る。

 

 

Overlayってやつは

UMGはレイアウトする際に、ポジションを管理する方法が大きく分けて2種類あります。基準点となるアンカーの存在の有無です。

またUMGの表示優先は、CanvasPanel内のものはZOrderで制御できますが、アンカーを使わないOverlay系のものは、ZOrderというプロパティが存在せずHierarchyのみで制御されます。

HorizontaBox は Overley系に属するため、中の子WidgetにZOrderを設定していても関係なく、Add Child した順に描画されるようです。

 

ひとまずカードのベースと絵柄を別々のパーツにしてみる。

 

すると・・・

これは UMG ではなく OMG!

 

デバッグツール Widget Reflector で見てもよくわからず。というか ZOrder 的なプロパティが無いことに気づく。

いろいろ調べてようやくたどり着いたのがこのブログ。

kumasan-debug.hatenablog.com

K.Y.さんありがとうございます。

 

エンジンのプロジェクト設定を変えることで対策できるようですが、結局手札としてのふるまいを考えると、HorozontalBoxだと表現しきれないと判断してCanvasPanelで実装することにしました。

それはそれで、並べるのに苦労しました。

 

 

MPCを使うパーツが増えたということは

スポット表現が必要なパーツが増えたことで、MPCを乗算するマテリアルが複数必要になる。そこでマテリアルファンクションを作ってラクしようと思いついた。

一応スケールを調整できるようにしてあるけど、初期値として3.2と2.0は入れておく。

これでパーツごとにこのマテリアルファンクションをノードとして取り出してつなぐだけで、スポット表現が手に入る。

パーツごとのマテリアルにノードを置いていくだけ。


こんな感じにできました。

詰めてみると

パーツをわけたので、左きき対応してみた。

 

 

 

リトルノアクリア

面白かった。昭和のアーケードゲーム程度のボリュームで個人的にはちょうどいい感じ。お値段もお買い得な感じ。吉田明彦さんの絵が好きなのもある。

littlenoah-s.com

作業にならないようにランダム要素をベースにしつつも運に振り切ってる感じはしないし、結構細かい調整を感じる。操作感も悪くない。敵を浮かせる技を持ったアストラルが多いのでエーテルスラストという空中ダッシュを混ぜた空中コンボが気持ちいい。その辺を意識した滞空時の追撃エフェクトを持ったアクセサリーがあったりと、なかなかの手厚いフォローのアクションが楽しめる。出会ったアストラルや拾ったアクセサリーによってコンボスタイルが変化するのもなかなか飽きさせない要素だと思う。開始時のスタメンは毎回固定なのも、ゲームシステムに慣れるまでは心強い。途中でどんどん強いアストラルに出会うので入れ替えてみたくなります。

『ノーダメージで』『制限時間で』『既定のダメージ量で』『既定のHit数以上で』など部屋にミッションが設定されることがあって、達成時の追加報酬があったり、強敵の発生する部屋があるのだけれど、装置を起動しないとスポーンしないので、自信がないときはスルーできる。もちろんクリアすると大きな報酬が手に入るし、バーストゲージも溜まる。慣れてきたプレイヤー向けに難易度の幅が提供できているのは素晴らしいですね。

ステージ攻略中は遊びごたえが十分あるけど、拠点でできることは結構シンプルで、キャラ周りの世界観に浸るには物足りない印象はある。でもこれくらいが個人的にちょうどいい。最近のスマホゲームで拠点というかホーム画面で情報過多なゲームが多すぎる気がする。各種ボーナスを受け取るのはモチベにはつながっているとは思うけど、ホーム画面でいろいろあちこちタップしても、ゲーム体験としては「遊んでない」のと同じじゃないかと思う。時間を消費するなら少しでも楽しいゲームプレイ体験が残るようにしたいと考えているので リトルノアのゲームデザインは個人的に気に入ってます。

 

 

ではでは

今回はこの辺で

検証内容的にあまり参考にならない気もしますが

ステキなカードゲーム開発ライフを!

 

雑記#20220710

ひさしぶりに書きます

ネタが途切れたのもあって、少ない脳ミソのリソースを会社員モードに全振りしていたらいつの間にか梅雨が明けて蝉が鳴く季節になるまで放置。さすがに寂れるだろうと思っていたんですが、しみじみと閲覧数を維持できているのは驚きと同時に感謝の念でいっぱいです。

UE5への移行で何か書けることあるかなと思ってアップデートしてみたものの、思いの外すんなり手癖を受け入れてくれる懐の深さ。いつも通りな感じで操作できてしまう自分がいるのでした。

差分情報などはすでにいくつかトピックが上がっていたりで、これといって新鮮なネタを思いつかない自分の役目は終わったな、などと書かない言い訳を拾い集めるのが心苦しくなってきたころに、ようやく方向性が見つかった気がしてきた今日この頃です。

 

過去記事をUE5でリフレッシュするのも考えてはいたけど、新しいことをしたい気持ちの方が強くて、UMGでもっといろいろ作ってみようと。その過程でネタが見つかるんじゃないかと。あとTwitterで晒して「それってどうやってるの?」みたいな反応があれば記事にしたらいいんじゃないかと。

まあそんな感じで、前置きが長くなりましたが、Twitterにあげたネタからいくつかピックしてツラツラ書いてみます。

 

 

スタイライズドなファイヤー

ここでいうスタイライズド(Stylized)という語は、記号化、様式化されたというニュアンスで使っています。ただリアルに物理現象を模すのとは対照的に、印象として記号感を残しつつもある特徴的なルールに従って表現されているので、アーティストの考えた世界観がぐいぐい出てくる。

たとえば、既存のアウトラインフォントを使うとき。フォントワークス社のラグランパンチやマティスEB、ロウディなんかを、ゲームで使うのはなかなか難しいのと状況が似ていると感じてます。

「難しい」とぼかして書きましたが、その特徴的な印象とプロダクトが1対1の関係に紐づいてしまうと、後から第3者が使うというのは、リスペクトかパクリかどちらにせよポジティブな印象に転化するのは簡単じゃないという意図です。

 

今回の炎は、過去に見たツイートで紹介されてたテクニックで、URLを遺失していたので記憶を辿りながら再現を試みてみました。確か英語で図解されていたと思います。原理的なものはそんなに外れてないはず。

 

フォントはボリュームのことを思うとアレンジするコストが膨大なので速攻で諦めるのですが、炎のマテリアルくらいだったら、がんばったらいろいろ工夫転用したり新しいヒントに出会えるかもしれません。ということで今回作ったやつを公開することにします。

 

ここからいくつか閲覧注意な画像が登場します。

 

 

肝になったテクスチャですが、シームレスで作る必要があって、Photoshopのパターンプレビュー機能(ver22.0以降)が大いに役立ちました。

適当な大きさのテクスチャに円形のシェイプを一つ。塗りを円形のグラデーションにします。

このシャイプレイヤーのブレンド効果を比較(暗)にします。

あとはこれを複製(Ctrl + J が便利)しつつ大きさを調整しながらひたすら埋め尽くします。適当にランダムに。

トライポフォビアの方ごめんなさい。ちょっとキモくなるけど、そこは我慢するか、グラデーションマップを一番上においてマイルドにするといいかも。

なぜかスマートオブジェクトにするとこの後の作業でブレンドがうまくいかなくなるので、ここはレイヤーグループにまとめます。

表示メニューからパターンプレビュー機能を有効にし

レイヤーグループを、コピーして8方向に移動。

移動量はテクスチャサイズと同量。

数値を気にしながらドラッグするのが面倒なときは、ざっくり動かした後でドキュメントを拡大してカーソルキーでドット単位でズレがなくなるように調整するといいです。

これでシームレステクスチャの完成です。

恐ろしいパターンプレビューを終了して、テクスチャとして書き出します。

これをマスクテクスチャとしてエンジンで利用します。

 

参考までにインポート設定。

用途がマスクなので、Grayscaleを選択。sRGBを無効にする場合、

マテリアルでは LinearGrayScaleとして扱うことになります。

 

炎は自然現象なので、基本繰り返すことはありません。でもテクスチャを使用すると同じパターンが繰り返し現れてしまいます。それをなんとかしてランダムに見えるように工夫しています。

 

あくまでも一例ですが、2種類の動きをレイヤーとして作っています。

まずはレイヤー1

パラメータノードを使っているのは、同じマテリアルを使用した場合に同じ動きをしてしまうので、意図的にばタイミングなどにバラつきを与えるためです。

Pannerノードでスクロールスピードを調整。

TimeからSine(サイン)ノードの流れは、左右に揺らすためのものです。

 

次にレイヤー2

構造の基本はレイヤー1と同じで、スピードの調整であえて差が出るようにしています。

2種類の最小公倍数を可能な限り大きくする感覚です。

 

2つのレイヤーを掛け算したものを確認してみます。

Named Rerouteノード便利ですね。多用すると追いかけるの大変になるけど、ノードに名前が付くので分かりやすい。状況確認しやすいのもGood。

こういったお試しの

 

これに調整を加えてから丸く切り取って、2諧調化して仕上げます。

Grayscaleはチャンネルを一つしか扱わないので、RGBAという4つにまとめられたFloatのうちの一番目、Rを使うので赤としてプレビューされます。

ですが、

最終的に流れてきたデータが、Rしかないときは、エンジンは気を利かせて、残りのGとBに同じ値を入れてグレーで描画してくれます。

MaterialのBlendModeを Additive にして完成です。

 

これをUMGに持っていって配置。

大きさを変えて2枚重ねにすることで、厚みと透明感を表現。

適当に着色すればいろいろ楽しめます。

 

Stepノード使うとトゥーンな見た目になるので、Stepノードを使わずに

SmoothStep とグラデーションテクスチャで、こんなやつも作れます。

知恵と勇気とこだわりがあれば、何とかなりそうな予感。

 

 

ビットでRGB

いわゆる光の3原色といえは、おなじみRGBの赤緑青です。

最近はHSVでカラーを調整するのがデフォという若者が増えて、嘆かわしいことですな。ふむ。

とかなんとか言いながら作ってみたのがこのパズルっぽいやつ。

狐の持つ炎の色が 赤、緑、青、のどれかに決まっていてランダムに配置。2匹が組み合わさることで、合成された色になるので、そこから組み合わせの内訳を推測して並べなおすという遊び。1匹だけサボってるやつがいるので、そこで確定させるとヒントになります。上の図だと、右端の2匹のうちどちらかがサボりで、どちらかが青。

 

この遊びを作るにあたって、ビットを使って制御したり判定することを思いついたのでいろいろ試した。

 

RGBのビット順については、勝手に下図のように決めました。

加法混色ということで、基本的に2進数で考えると扱いやすい。

というわけで整数にして扱うようにしていますが、その値にRGBの各要素が含まれるか調べる必要がある。その方法で使ったのがビットマスク。

 

任意の整数から、RGBが含まれているかチェックして、カラーに置き換える関数。

&というノードは ビットでの論理積で0と1の掛け算。

この”&”(AND)を使い、特定の狙ったビットだけを残して 0か1かをチェックすることで、そのビットがどういう状態なのかがわかるというもの。

 

こんなことせずとも、RGBそれぞれ個別に配列作って管理してもいいんですけどね。

ちょっとやりたかったというか、まぁ自己満足ですね。

 

 

 

灼熱のサドル地獄炙り

昼休みに出かける際 暑いのでさっさと行って帰ってくるのがベスト。で、自転車に乗るのですが、屋外に停めてあるので黒いサドルがとんでもなく熱くなっていて、立ちこぎするしかない状況になる。尻の肉が焦げてしまいそうなくらい熱くなっている。気がする。そこでふと頭に浮かんだのが、料理名のような灼熱のサドル尻肉の地獄炙り。

語感も悪くない気がする。尻肉がなんかイマイチなので、肉の部位名を調べたら「イチボ」というらしい。テールはしっぽの付け根だし、ランプはもう少し上の腰のあたり。尻側のもも肉ということでイチボ。焼肉食べにいきたくなってきた。

それにしても普段エアコンのある場所で生活しているので、年々暑さ寒さに対する耐性が下がっている気がする。

 

 

 

ではでは

今回はこの辺で

 

P.S. ウィンルキンソンのパイナップルフレーバー炭酸が好きすぎる

 

 

 

 

UIチャレンジ振り返り

もう年末、プロジェクトは終わってないけど年内分の仕事もなんとなく納まったのでやれやれです。年々体力に自信がなくなっていくのがヤバイですね。

 

この7月から参加している UIチャレンジ企画 について作ったものを振り返ってみようと思い立ったので、記事にまとめることにしました。

 

この企画は、「皆で楽しむUIチャレンジ」をコンセプトに、デザニメ・ラボ さんがTwitte上でお題を出して作品募集、レビューを動画で配信もされています。

twitter.com

 

最近のから順番に振り返っていきます。

 

第12弾 ストアレビューダイアログ画面を作ってみよう!

f:id:hiyokosabrey:20211226171040p:plain

 

お題は

 

四角いウィンドウはやめよう、角丸もちょっと違うな、というところまで考えてはいたものの、結局前日まで作業しなかったのはちょっとだけ後悔。

年末にかけての気ぜわしさと、ブログの記事が思うように進まなかったのもある。

ほとんどラフだけど、なんとか投稿はできた。

 

 

ぼくは ある程度遊びこんでから判断したいので、ストアレビューダイアログが出てきたらすぐに閉じてしまう。なのでわざわざ専用で手の込んだダイアログが出てきたら、諸々リソースの使い方として勿体ないんじゃないかと気になったりする。1点もので1度条件を満たせば2度と出なくなるようなUIは、常駐させないようにしてなるべくエコなつくりを目指す。

とはいえせっかくのUIチャレンジなんで、普通だとやらない表現を試すのも楽しみ方のひとつだと思う。

評価の☆をつける時の雰囲気を少しでも変えられたらいいな、と考えてクリスマスツリーのオーナメントに見立てて並べられるようにしてみた。

雰囲気的に、☆をツリーにつけるときの動きを直線的にしたくなくて、いい感じのカーブにするにはどうすれば・・・と悩み始めたときにはもう締め切り前日。

投稿後にベジェ曲線で柔らかいカーブでやろうと思ったりしたので、スプライン補間について調べてUE4で実装したのがこれ。

 

 

投稿した時の絵だと、操作方法を誘導できていないので、クリック位置を示す表示をツリーに加えた。

 

 

 

 

第11弾 武器強化のレベルアップ画面を作ってみよう!

f:id:hiyokosabrey:20211226173146j:plain

 

お題は

 

演出メインか~エフェクト頑張るかな~、とちょっと余裕かましつつレイアウトを考えていたら、はたと気づいてしまった。これはビフォーアフター のいるやつや!

レベルアップとレベルアップ後の差分を作る必要が出てきた。そこでいろいろ流れを考えていたら、結構ガチな遷移を考えることに。結局そこそこ手間がかかることになった。

 

武器の名前を考えていた時に、ふとレトロな表現がやりたくなって、Photoshopのシェイプで作字にチャレンジ。

f:id:hiyokosabrey:20211227152244p:plain


読みは キフツマル かな。赤色にしたときにそれっぽくなったので満足。

せっかくレトロ感のある武器のロゴができたので、全部昭和にしてしまえということで、昔のゲーム攻略雑誌みたいなテイストにすることに決める。

今ほど自由度の高い DTP環境がなかったので、あまり手の込んでないシェイプやグラデーションを使っていくスタイル。

 

仕上げとして、フィルタ的にハーフトーンの点描を加算半透明でかぶせて、昔の印刷物の雰囲気を醸してみたけどどうだろう。

f:id:hiyokosabrey:20211230131905p:plain

 

 

武器に日本刀を選んだので結構苦労した。最近は資料が溢れまくってるので、テキトーに描くといい加減なのがすぐにバレてしまう。柄巻きは意外に奥が深いことが分かった。鍔や下げ紐のバリエーションを、武器のレベルで変えたかったけど、時間の都合で断念。結局鞘の蒔絵が描き足されていくことでグレードを表現。

f:id:hiyokosabrey:20211230132830p:plain最後のレベル、月に鳥(ホトトギス)は花札を参考にして描いた。

 

 

 


フローとしてこんな感じ。

f:id:hiyokosabrey:20211230135652p:plain

 

次レベルのスペックを確認してから、上げるかどうか考える仕様。

 

今改めて見直すと、次のレベルを確認する際に、一時的な表示であることをあまり強調できていないので、上げた気にならないかが懸念。

 

用意するアセットが多くて大変だったけど、楽しかったので、ガッツリと作ってしまった。

 

 

 

 

第10弾 ハロウィンガチャの結果画面を作ってみよう!

f:id:hiyokosabrey:20211226215006p:plain

お題は

 

イデアはありつつも手を付けるのが遅かったので、絵を描き始めてから間に合わないことに気づいて、絵コンテでの参加。

カメラ移動の都合で2枚目は下から上という変則的なナンバリング。

かぼちゃの吐く煙でちょっとだけアイデアがあったので試してみたかった。

素材に時間がかかるタイプは、まとまった時間を作らないと、思うようなクオリティに持ってくのが難しい。

多人数で開発していると、キャラや背景はお任せすることが当たり前になってしまっているので、素材を用意することを失念しがち。

 

割と冗長かなと思ったけど、常設のガチャと違い、ハロウィンイベント用ということで、ちょっと特別感を出せば、多少長めの演出でも大丈夫かな?という判断。

ガチャならではの「何が出るかな?」感は煙からシルエットをフェードインで演出。

煙で画面を埋めると、その後の画面遷移がラクなので。

 

場面は、どこか西洋の豪華な屋敷のカーペットの敷かれた広間。

古風で使い古された演出のステレオタイプだけど、なんとなくハロウィンに合いそうと思った。

 

 

 

第9弾 ポップな図鑑(子ども向け)画面を作ってみよう!

f:id:hiyokosabrey:20211226215554p:plain

f:id:hiyokosabrey:20211226215608p:plain

 

お題は

 

今見ると、フツーに子ども向けで、ポップさはどこに?という感じ。

ゲームが存在するとしたら、タネのグラフィックはキチンと描き込まれている想定。

 

お題が「子供」ではなく「子ども」だったので、勝手にターゲットの年齢を低めに設定。

純粋に図鑑を喜ぶ年頃だとしたら、小学校上がる前かなということで、操作ナビ表示をハンドサインで示そうと試してみた。

f:id:hiyokosabrey:20211228103208g:plain

こういうシンプルにループするパターンアニメーションはシェーダーにやらせると、タイムラインを消費せず、アセットも分けなくてよくてメリットが大きい。タイムラインによるフェードイン/アウトを重ねやすいのもいい。

戻るボタンについては、押したらすぐに大きな反応があって学習コストが低いのと、押した結果に時間消費以外のリスクがほぼ無い設計なので、シンプルにピクトアイコンを採用。

 

結構テクスチャの作りに手間取ったのが虫眼鏡の動き。

f:id:hiyokosabrey:20211228104558p:plain

虫眼鏡越しにチラ見せするをいい感じにパターン化するためにPhotoshopのマスクを工夫しながら調整。

f:id:hiyokosabrey:20211228105103p:plain

これもずーっと勝手にループしてるやつなので、タイムラインを使わずにパターンアニメーションさせるためにシンプルなシェーダーを用意。

f:id:hiyokosabrey:20211228105953g:plain

 

なるべく絵の情報量をタネに集中させるために、UIの質感表現は極力減らした。

という言い訳が通じればラッキーだなと思いながら、調整に時間がかかるドロップシャドウやグラデーションは控えめにした。

UE4使って作ってみたかったのもあって、絵素材を用意する時間を減らしたかったというのも言い訳としては大きいかな。

 

 

チェレンジって、きっと Challenge のスペルが混ざってタイプしたのだと思う。たぶん。

 

 

 

第8弾 VTuberライブ配信準備中の画面を作ってみよう!

f:id:hiyokosabrey:20211228194010p:plain

f:id:hiyokosabrey:20211226220216p:plain



お題は

 

ジャンルは、ポップ、キュート の指定。

ポップさは色数をたくさん使いつつ、キュートさはお花と小鳥を、と考えたのが最初のやつ。

f:id:hiyokosabrey:20211228195459p:plain

色の帯 1本毎にマテリアルインスタンスでパラメータを調整しながら絵がつながるようにした。

f:id:hiyokosabrey:20211228200135p:plain

f:id:hiyokosabrey:20211228195550p:plain

またこの色の帯の優先順位をばらつかせるように個別に設定して、小鳥のパーツを飛ばすと間を縫って飛ぶような見せ方ができる。

ちょっと北欧風過ぎたのと、他の方の作品を見てると、キャラが居たほうがそれっぽいなと思い立ち、急いでキャラを描いた。

なんとなく水棲生物系モチーフは少なそう、と勝手に判断。

キャラはできたものの1つ目のと全然合わない感じなので、新しく画面を作り直すことに。

ループ素材としてカラフルなウェーブを雲海に見立てて、多重スクロールで奥行き感を演出。文字は流そうかと思ったけど、魚つながりで、飛び跳ねてる方が面白そうだったので、放物線の動きをネットで調べてブループリントで実装。

 

 

キャラが上下に揺れるのは、動きが単純なのと緩急が一定なのでタイムラインでやるより計算したほうが効率的と判断。

f:id:hiyokosabrey:20211229113216p:plain

サインカーブほんと便利。

こんなに使えると知ってたら、数学の成績上がってただろうな。

 

そこそこ頑張って描いたので高解像度版を貼って供養。

f:id:hiyokosabrey:20211228193555p:plain

 

 

 

 

第7弾 ファンタジーゲームのショップ画面を作ってみよう!

f:id:hiyokosabrey:20211226220447j:plain

 

お題は

 

ファンタジーのショップといえば、禿頭のムキムキマッチョ親父が真っ先に浮かんだけど、ムサイ絵にしたくなかったのと、店の近くでボタンを押すとリストが出てくるタイプのはフツー過ぎるでの、ちょっとだけダイエジェティックにしたかった。

そこでアイテムの形が分かりやすく見せるには、カウンターに並べるのがよさそう。

たくさん並べられないのが難点だけど、ファストトラベルとかがある想定なら大丈夫。

と勝手に納得して描き始めたものの、慣れないタッチで挫けそうになった。

 

布の色で効果のカテゴライズ、形でグレードを表す仕様。

例えば緑の布は 体力回復 とすると、どこのショップでも体力回復系は緑。効き目が大きいほど、房飾りがついたり、装飾性が上がっていく。効き目がしょぼいと、ぼろぼろになっているとか。

 

ゲームの世界観についても考えながらなので、それなりに時間がかかった。

カウンターの向こうにいるのは、店主兼魔法使いである黒猫(瞳しか描いてない)と店番兼魔法使いの弟子

UI自体はシンプルで、UE4で作ろうかと考えていたけど、時間が取れずに静止画で投稿。

実際作るとなったら愛らしいキャラモデリングでかわいいボイスでいい感じにアクションしてくれると思う。

 

 

フリーカーソルで瓶を選ぶとそこでようやくアイテムの詳細と値段が分かるというのは、せっかちなDだとまぁ普通は NGが出ると思う。

 

表現力が上がって、世界の情報量が増えてるいるからこそ、まったり本気のロールプレイができてもいいんじゃないかと思う。

 

 

 

 

第6弾 ログインボーナス画面を作ってみよう!

f:id:hiyokosabrey:20211226220607j:plain

 

お題は

 

テーマはジャンル不問。

補足に、ログインボーナスのロゴだけでもOK。キャラや背景にフリー素材を使ってもOK。

とある。

 

8月入って暑い盛りで、なんとなく夜祭のイメージで、お狐様かな~と思って描き始めたラフ。

f:id:hiyokosabrey:20211230110203j:plain

ただ並べるだけなのもつまらないので、アイスを積み上げてみる。

途中で食べると、ボーナスのグレードが上がらない仕様を考えて、説明がいるなと思ったので、フキダシを乗せる。

 

ちょっとモルカー味を足してできたモッチリお狐様が誕生。

f:id:hiyokosabrey:20211230110732p:plain

 

画面上部のカマボコ ●●●●は最初アイスクリーム屋台の庇(ひさし)のイメージだったけど、カメラに近いというか、見ている方への圧が強いので、祭りの提灯のイメージに変更。

 

 

このチャレンジで さくの賞 をいただくことができた。

いただいたAmazonギフトで気になってた本をゲット。

 

 

 

第5弾 何度も見たくなるローディング画面を作ってみよう!

f:id:hiyokosabrey:20211226220958p:plain

お題は

 

補足に、ネタ要素やストーリーを入れたりなど工夫して、「もう一度見たい」

と思わせるローディングを考えてみよう!

とある。

 

ヒトは同じパターンが繰り返されてるとわかったとたん興味を失ってしまう生き物。

常に新鮮な体験を求めているものなので、ランダム要素は必須。

さらに何らかの報酬が脳内に生じればカンペキ。

とはいえ、ゲームの本編を遊びたいのに遊べない時間なのはストレスでしかないので、ローディング画面が好きな人はまずいないと思うし、ローディング画面を見るためにゲームをプレイしているわけではないと怒られそうなので、できる限り簡素に作るのが基本として今まで生きてきた。実際ロード時間(+メモリへの展開時間とかモーションのセットアップとかセーブデータの反映とか諸々含んでる)を少しでも短くするするために、バックグラウンドで処理したりシビアなメモリ管理をエンジニアの手によってなされている。なかなかUIに処理を割いてくれと言いにくい。

コンソール機では、一定時間以上になればプレイヤーに有益な情報を表示しなさいとか、文言縛りとか、いろいろレギュレーションがあったりする。画面がフリーズしていないことを表すための動きが最低限あればまぁ大丈夫。

 

で、何が釣れるかな?というドキドキをメインに考えてみた。

釣り上げるのは、TEXTURE とか ゲームを構成する何かをテキストにしたもの。

 

 

テクスチャアトラスはこんな具合。

f:id:hiyokosabrey:20211230101302p:plain

 

UVの範囲にカラーをつけるこうなってる。

f:id:hiyokosabrey:20211230101625p:plain

 

竿のカーブが一番難しくて時間がかかった思い出。

 

もうひとつおまけで作ったのが、簡単なシェーダーで動くやつ。

 

 

 

第4弾 夏をイメージしたフレームデザインを作ってみよう!

f:id:hiyokosabrey:20211226221351p:plain

 

お題は

 

テーマが、 青空・海・スイカなど夏をイメージさせるデザイン

 

最初に考えたラフ

f:id:hiyokosabrey:20211230093441p:plain

雰囲気は気に入ってたんだけどうまく描ける気がしなくて断念。

夏といえば、空は青く雲は白く眩しくということで、思い切って2色で描いてみようということに決めた。

なんとなくオシャレなリゾート地のボートハウスなんかにありそうな看板をイメージ。

あとはとにかく四角いウィンドウにするのがイヤイヤ期なので、雲のシルエットを出したり、下は波のイメージでカット。

 

 

ネタ的にカモメのスクロールバーがお気に入り。

下のでっかいヒトデや貝のモチーフは、ボタンを想定。

f:id:hiyokosabrey:20211230095300p:plain

 

 

 

 

第3弾 ゲーム終了時の「CLEARの文字」を作成してください。

f:id:hiyokosabrey:20211226221625p:plain

f:id:hiyokosabrey:20211226221637p:plain

 

お題は

 

テイストに サイバー風デザイン の指定。

何をもってサイバーとするかとても難しくて、よく見るのはステレオタイプのものがほとんど。仮に定義しても、「カッコイイ」「カワイイ」のように個人差が大きいので、ナンカチガウ になりがち。とりあえず、斜め線 と 半透明、グロウ(発光)の要素を入れておけばそれっぽくはなるけど、何か革新的なテクノロジーに紐づくモチーフ(最近ならHMDとかARグラスがポピュラーかな)を匂わさないと、ディスプレイ表示だけで新しさを出すのは難しいなと思う。

とかなんとか分かったような分かってないようなことを書いてるけど、とりあえず無駄そうに見える幾何学的なラインを光らせたり重ねて視差を作ればええんとちゃう?

というのが落としどころかと思いつつも、リザルト画面として使えるようにしてみた。

 

 

QRコード は 3か所のを1pxのブラシ(鉛筆)で描いて 2階調化したノイズ重ねる。それをニアレストネイバーで拡大して完成。

 

f:id:hiyokosabrey:20211230085844p:plain

 

一応コードリーダー通してみて反応がなかったので(ホンモノはデータサイズが規格化されてる)、デザインモックとしてはバッチリ。バーコード的なものもサイバー風かなと思って置いた。

かつてのアーケードゲームってオンラインじゃなかったので、リザルト画面に出たQRコードを ケータイ で読むとランキング登録できるという仕組みを提案したことがあった。いろいろ大人の事情で実現しなかったけど。

今はもうスコアを勝手にアップされる時代なので、コンソールのゲーム画面でクーポンコードを発行して、それをスマホから利用できるようにするとか?

 

画像が小さいとちょっと見えにくいので部分拡大。

f:id:hiyokosabrey:20211230092623p:plain

実装はできてないけど、レンダーターゲット使って、レイアウトをいったんキャッシュ。シェーダーでモザイク化したやつを加算する想定。

 

 

 

第2弾 ゲーム開始前の「スタートボタン」を作成してください。

f:id:hiyokosabrey:20211226222124j:plain

 

お題は

 

テイストに 和風イメージ が指定されてて、きらびやかで雅な感じのモチーフは、まぁ誰かやるでしょう、ということで趣を変えてみた。

紙の白に朱色だけを使い、全体的に紅白のめでたい感じを演出しつつ、フラットベースで大き目のモチーフをあしらうことで、地味にならないようにしてみたんだけどどうかな。

 

 

デパートとかショッピングモールの新春初売りセール広告みたいと言われればそんな気もする。

 

第1弾 「スプラトゥーン2」と「ウマ娘」からインスピレーションを受けて、オリジナルの「OKボタン」を作ってください。

f:id:hiyokosabrey:20211226224150p:plain

 

お題は

 

このツイートが始まりでした。

この時はまだ、デザニメ・ラボ発信、というより はなさくの さんの公開チャレンジで、並走ウェルカム!といった趣の企画。

 

版権の絡みそうなものは避けたがる体質なので、参加しようか躊躇ったけど、水タイプと草タイプというか軸の合わなさそうなモチーフを合わせようという大胆なチャレンジに興味が湧いた。

 

シェーダーを使っていろいろ遊んでた頃なので、輪っかを揺らすことでスプラのリキッド感を表現。ウマ娘は、決定時の演出効果を真似る感じで。

f:id:hiyokosabrey:20211226232755p:plain

f:id:hiyokosabrey:20211227212915g:plain

 

 

 

もう半年前になるのか、ちょっと懐かしいな。

 

 

参加してみて

第12弾まで全てに参加できた。皆勤賞!

 

ネタが思いつけないと「今回は不参加でもいいかな」って考えつつ日々を過ごしてしまい、締め切りが近づいてくると、そわそわしてくる。

ある時、

 ─── ここで降りたら、逃げたことにならないか?

と思うようになった。使命感に目覚めたということか。

今までのUI開発経験を思うと、それなりの数をこなしてきた自負のようなものが少しはある。どんなテイストでもデザインできるのがプロってやつだとするなら、UIチャレンジのどんな弾でも立ち向かって解決できないと、あるかないか ほとんど意識したことないプロ意識とはいえマジで無かったことになってしまうとさすがにつらい。

 

とかなんとか、真面目そうなことを書いてみたけど、実際はそれなりに楽しみつつ、自分なりのチャレンジができて収穫もあった。

 

UIを好きにデザインするのは難しくて、なかなか本腰が入らない。アートディレクターやディレクターのOKが出るまでは、ラフというか仮デザインというのに慣れてしまってるのもあって、UIチャレンジも丁寧に仕上げて出せていないところが結構ある。このあたりちょっと罪悪感みたいなものが残ってたりするのはこの長年の習慣のせいだと思いたい。

あともうちょっと言い訳すると、Photoshopでレイアウトをキッチリ組んでOKもらっても、テクスチャに落とし込むときに、中途半端な大きさだったりして、調整することがほとんど。特にインタラクションで発生するエフェクト素材は、サイズが読みにくかったりする。デザインチェックの段階で、ピクセルレベルで仕上げてしまうと、実装する際に詰んでしまうこともしばしば。キッチリしたものにOKもらってるぶん変えるのをためらってしまうことになる。

この辺はプロジェクトや現場の人間関係、信頼度によるところも大きいので、環境が変われば、採れる戦略も多少変わってくる。

ぼくの場合は80点くらいの完成度でプレゼンする。OKが出たらさっさとアセット作ってエンジン上で90点くらいに整える。残りは、他のUIが出揃ってきてからゲームを触りながら調整することが多い。

何かを固定するための複数のネジを締めるとき、ひとつずつを確実に締めていくやり方は、歪みが出たときに他のネジに負荷が掛かるし、直すのが大変になって時間がかかってしまうというのを学生のころ学んで、今でも大事にしている。

 

決して手を抜いてるわけでもないけど、渾身かといえばそれほどでもないところはやむなしと自分に言い聞かせつつ、UIチャレンジでの自分の役割は、他の参加者に少しでも刺激になれるように、ちょっとでも大胆に、そして誰もやらなさそうな方向性を提案することだと思って作ってた。

別にコンペでもないし、優劣とかなくて気軽に参加できるのがいい。「なるほどその手があったか~」といえるものに出会えるのが楽しみでもある。

というわけで、2021年 デザニメUIチャレンジ 何とか走りきれた。

開催してくださったデザニメ・ラボさん のお二人、はなさくの さん、たかゆ さん、参加された皆様おつかれさまでした。

来年もできる限り参加したいと思います。

 

f:id:hiyokosabrey:20211230145856p:plain

 

ではでは

ステキな UIチャレンジライフを!

みなさまお年を

 

 

3DメッシュでつくるUI ー 矢印をつくる

ゲームのUIを作っていると一度くらいは矢印をデザインすることがあると思います。今回は動きのある矢印を3Dメッシュでつくります。動きといってもUVのスクロールです。テクスチャのUVを移動させることで絵が流れて見えるやつです。

f:id:hiyokosabrey:20211211105058g:plain

 

前回の記事で使ったカーブを応用するとこんな矢印も作れます。

f:id:hiyokosabrey:20211211115531g:plain

ひとつのメッシュから法線の向きを反転させたもう一つのメッシュを作り、それぞれ違う色のマテリアルをセットし同じ位置に表示すると、裏表で色が違うという表現ができます。Backface Culling(陰面消去)でそれぞれの裏面は描かれないというのを利用しています。

 

f:id:hiyokosabrey:20211217202348g:plain

このウネウネはテクスチャの歪みを抑えるために頂点数は結構多いですが、

f:id:hiyokosabrey:20211217201530p:plain

 

テクスチャサイズは64x64です

f:id:hiyokosabrey:20211217185422p:plain ←実寸

テクスチャを繰り返して並べることをタイリングといいます。前回の記事で書いたWrap(ラップ) と Clamp(クランプ) の設定で、Wrapを使っています。

f:id:hiyokosabrey:20211205220858g:plain

 

 

 

矢印の作り方はいろいろあって、手間 容量 をどう案配するかがカギで、クオリティに差が出ます。

 

とりあえず一番上で紹介したシンプルなアニメーションの矢印を作ってみます。

簡単なカタチの矢印をポリゴンで用意します。

いろんな作り方がありますが、ぼくなりの一例をご紹介します。

 

作業する面は XY (テンキーの[7])

f:id:hiyokosabrey:20211219133401p:plain

プレーンな四角形を追加

Object Mode > Add > Mesh > Plane

f:id:hiyokosabrey:20211219101759p:plain

f:id:hiyokosabrey:20211219103049p:plain

 

Edit Mode にしてエッジを1本だけ選択。

f:id:hiyokosabrey:20211219103142p:plain

 

[E]キーを一回だけ押して、選んだエッジの方向に[G]キーを押して移動すると、ポリゴンが増えます。

移動の際、途中で[Ctrl]キーを押すか、中ボタンで移動開始すると移動方向を拘束できて便利。

f:id:hiyokosabrey:20211219103219p:plain

 

そのまま エッジを 分割します。

Edit Mode > Edge > Subdivide

見た目にわかりにくいですが、エッジの中間に頂点が増えてます。

その増えた頂点に向かって、ナイフツールでエッジを引きます。

f:id:hiyokosabrey:20211219104433g:plain

ナイフツールは、マウスカーソルが頂点に近づくと、大き目の □ が表示されるので、それを手掛かりにクリックしていきます。最後に[Enter]キーを押して確定。

 

あとは頂点を動かして形を調整します。

f:id:hiyokosabrey:20211219104831p:plain

長さもいい感じに調整。

f:id:hiyokosabrey:20211219105801p:plain

 

テクスチャを作ります。

f:id:hiyokosabrey:20211219111230p:plain

  ↑

白黒半分ずつ塗り分けた 32x8 です。

これを Blender で読み込みます。

まずメッシュの頂点を全部選んでマテリアルをアサイン(割り当て)します。

f:id:hiyokosabrey:20211219113426p:plain

上図では、デフォルトのマテリアルを選んでますが、Newボタンをクリックすると新しいマテリアルが作成できます。

 

Use Nodes ボタンが青くなっているのを確認

SurfaceEmmision に変更

③ Color を Image Texture に変更すると テクスチャ選択フォームが出てくる

④ フォルダアイコンをクリックしてダイアログからテクスチャを選択

f:id:hiyokosabrey:20211219133024p:plain

 

 

UV展開します

頂点をすべて選択した状態で

Edit Mode > UV > Project from View(Bounds)

 

ビューポートを UV Editing に切り替えて確認

f:id:hiyokosabrey:20211219133847p:plain

テクスチャいっぱいに展開されます。

このUVを縦方向に潰します。

UV > Align > Align Y

または右クリックしてコンテキストメニューからも Align Y が選択できます。

f:id:hiyokosabrey:20211219134152p:plain

 

ちなみに、UV展開の前に、カメラの向きを変えるのも同じような結果にできます。

テンキーの[1]を押してメッシュの見えてる角度を変えてから

f:id:hiyokosabrey:20211219134456p:plain

Edit Mode > UV > Project from View(Bounds)

すると、UVがこうなります。

f:id:hiyokosabrey:20211219134723p:plain

どちらの方法でも結果オーライなら問題なし。

 

UV展開完了。

この段階で、エンジンに持っていけます。

 

せっかくなんで、Blenderでシミュレーションします。

ビューポートを戻して、シェーディングモードをマテリアルに切り替えます。

f:id:hiyokosabrey:20211219135004p:plain

 

f:id:hiyokosabrey:20211219135255p:plain

もうお気づきだと思います。

端っこの白い部分。

f:id:hiyokosabrey:20211219142630p:plain

UV展開の際には含まれていませんよね。

f:id:hiyokosabrey:20211219142423p:plain

テクスチャの端っこにも。

f:id:hiyokosabrey:20211219142825p:plain

 

反対側もうっすらと黒くなっています。

f:id:hiyokosabrey:20211219145644p:plain

これはBlenderでもテクスチャのタイリングで繰り返し(Repeat)が設定されているためです。

 

今回はこのままで矢印を作っていきますが、繰り返さない設定も可能です。

テクスチャを読み込んだ際にいじったパネルにあります。

f:id:hiyokosabrey:20211219143929p:plain

なんのラベルもないのですが、 Repeat(リピート) のところを Clip(クリップ)にするとテクスチャを繰り返さなくなります。

 

余談ですが

テクスチャのサイズより画面で大きく描画すると、テクスチャのピクセルがボケて滲みます。バイリニアフィルタのおかげなんですが、3Dでは、キャラとか背景とかテクスチャが素直にまっすぐ描画されることがまず無いです。またカメラとの距離が一定じゃないので、バイリニアなどのフィルタがないと、Photoshopの ニアレストネイバー(近傍補間)で変形させたような見た目になります。オノマトペで言うと「じゃりじゃり」とか「ざらざら」という感じ。

通常のメッシュに貼ったテクスチャにはありがたいバイリニアフィルタですが、文字などのエッジがシャープなものは、ボケやすいので解像度を落とせなくなります。

予期せず近隣の色が入り込むので、ゆとりを持ったテクスチャ作成が求められます。

今回のように低解像度のテクスチャを使う場合で、UVの端っこが気になる場合は、

f:id:hiyokosabrey:20211219150640p:plain

これで一応解決します。

f:id:hiyokosabrey:20211219150914p:plain

バイリニアの滲みは回避できたけど、見た目が想定通りじゃない。

テクスチャをいじらずに回避するには、

f:id:hiyokosabrey:20211219151504p:plain

UV座標にゆとりを持たせる。

f:id:hiyokosabrey:20211219151844p:plain

あとは、テクスチャの解像度をめっちゃ上げるのも効果ありますが、費用対効果をもとに要相談です。

この際バイリニアフィルタを効かなくするのも手です。

f:id:hiyokosabrey:20211219161300p:plain

Linear(リニア) のところを Closest(近接) にすると滲まなくなります。

 

さてさて

今回の矢印は、タイリングは Repeat(繰り返し)で進めます。

Blenderのシェーダーを使って繰り返しの回数を調整します。

ビューポートを Shading に切り替えると専用のエディタが開きます。

f:id:hiyokosabrey:20211219163406j:plain

画面下にノードが並ぶエリアがあるので、ここを編集していきます。

f:id:hiyokosabrey:20211219164056p:plain

Add > Vector > Mapping

f:id:hiyokosabrey:20211219164401p:plain

紫色のノードが現れるので、テクスチャノードの Vectorピン 同士をつなぎます。

f:id:hiyokosabrey:20211219164627p:plain

次に、

Add > Input > UV Map

赤色のノードが現れるので、UVピンと、Vectorピンとをつなぎます。

f:id:hiyokosabrey:20211219193440p:plain

必要なノードが揃いました。

パラメータをセットしていきます。まずは UV Map ノード。

ノード下部にあるフォームが空なので、クリックしてリストから選びます。

f:id:hiyokosabrey:20211219194039p:plain

メッシュに設定されるUVは普通は1つですが、複数のUVマッピング情報を持つことができます。

確認するには、ここのリスト。

f:id:hiyokosabrey:20211219194628p:plain

右の +ボタンを押すと増やせます。

 

次にMappingノード。

Scale の X を大きい数字に変えてみます。

f:id:hiyokosabrey:20211219195237p:plain

 

f:id:hiyokosabrey:20211219195716p:plain

f:id:hiyokosabrey:20211219195725p:plain

f:id:hiyokosabrey:20211219195733p:plain

いい感じの間隔になったら、次は Location の X を触ります。

f:id:hiyokosabrey:20211219201619p:plain

フォームをマウスで左右にドラッグすると、動きます。

Xの値がマイナスになるように動かすと、矢印の先端に向かって動くことがわかります。

これで重要な情報は揃いました。

 

タイリングの回数は Scale X(=U) で 10倍

スクロールの方向は X(=U)軸で マイナス方向

 

この情報を持ってエンジンでマテリアルやシェーダーを用意すれば実装できます。

スピードと色は、エンジンで調整するほうが確実です。

 

f:id:hiyokosabrey:20211219202914p:plain

f:id:hiyokosabrey:20211219202943g:plain

できました!

 

実装した矢印を見てもらったところ、フィードバックが返ってきた、という想定で、

もう少し手を入れていきます。

f:id:hiyokosabrey:20211219214543p:plain

ぐぬぬ

 

ということで、動くところと動かないところを分けることになりました。

とはいえ、UVを動かすと、すべての頂点が動いてしまいます。

 

そこで、テクスチャを上下に分けて考えます。

f:id:hiyokosabrey:20211219215416p:plain

上のレーンは、白と黒が交互に並び、下のレーンは、ずっと白のまま。ということになります。

メッシュの UVをうまく分けられればなんとかなりそうです。

 

テクスチャを更新します。

Photoshopで上書きしても、Blenderではすぐに気づいてくれないので、テクスチャを開きなおします。

ついでに UV座標を動かしておきます。

f:id:hiyokosabrey:20211220215204p:plain

 

動くところと動かない部分を分けるために、エッジを追加します。

 

Edit Mode で上下2本のエッジだけを選択して、

f:id:hiyokosabrey:20211219220701p:plain

ヘッダーメニューから Edit Mode > Edge > Subdivide

f:id:hiyokosabrey:20211219220726p:plain

この増えたエッジを右に寄せます。

f:id:hiyokosabrey:20211219221000p:plain

シェーディングモードをワイヤーフレームにしていたのでマテリアルにしてみると・・・

f:id:hiyokosabrey:20211219221204p:plain

なんと、テクスチャがひきつれてバランスがおかしくなってしまいました。

もう一度UV展開し直してもいいのですが、こういう時は、Option設定の
Correct Face Attributes(面の属性を修正)を利用します。

f:id:hiyokosabrey:20211219222346p:plain

アンドゥ (Ctrl+Z)してエッジを元の位置に戻すか、エッジを削除(Dissolve Edges)します。

改めて、エッジを動かします。

f:id:hiyokosabrey:20211219222756p:plain

 

動かしたくない頂点を選択します。

f:id:hiyokosabrey:20211219223611p:plain

 

UV Editor 画面で確認します。

下図のようになっていればOK。

f:id:hiyokosabrey:20211219223758p:plain

なっていなければ、UV Sync Selection(UVの選択を同期)を無効にします。

f:id:hiyokosabrey:20211219224119p:plain

下のレーンに移動します。

すべての頂点を選択して下図のようになればバッチリ。

f:id:hiyokosabrey:20211219224351p:plain

 

f:id:hiyokosabrey:20211219224618p:plain

これをエンジンに持っていって確認します。

f:id:hiyokosabrey:20211219225013g:plain

これなら大丈夫そうです。

 

ついでにもうひとパターンも試してみる。

f:id:hiyokosabrey:20211219234447g:plain

 

メッシュを分割してから、Correct Face Attributes(面の属性を修正)を無効にした状態で、エッジを動かすことで、スクロールスピードに緩急を付けることができます。

f:id:hiyokosabrey:20211220215946p:plain

一度割り当てたUVをそのままに、メッシュを変形することで、意図的にUVを引きつらせるテクニックです。

 

UVのスクロールをV方向に動かせるようにすると、アニメーションのON/OFFができます。

f:id:hiyokosabrey:20211220223413g:plain

f:id:hiyokosabrey:20211220222119p:plain

今回のテクスチャでは タイリングのY方向 を Clamp する必要がありますが、上図 OffsetV(ScalarParameter) の値を、0 で アニメーションあり。 1.0 でアニメーション無しにすることができます。

テクスチャが Wrap(またはRepeat)になる場合は、縦方向にゆとりを持たせ、移動量を +1ではなく +0.5 とかにするだけです。

スクリプト制御で値を書き換えてもいいし、マテリアルインスタンスを別々に用意しておいて差し替える方法だと色の調整とかもまとめてできるのでラクです。

 

 

いかがでしたか?

ただの矢印ですが、ちょっとした工夫でいろいろ遊べます。

ジャギー(エッジのガタガタ)の消し方とかも紹介したかったのですが、さすがに長くなったのでこの辺にしておきます。

 

メッシュとUVスクロールを組み合わせるといろいろ面白い表現ができるので、ぜひお試しあれ。

 

ではでは

ステキな3DUIライフを!