みつまめ杏仁

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

UMGでリストボックスを作ってみる 《おまけ》

前回作ったリストボックスにもう少しだけおまけを追加してみようかと。

 

limesode.hatenablog.com

limesode.hatenablog.com

 リストボックスは、全体の一部分しか見えていないので、「もうこれ以上ないよ」または「まだ続くよ」というのをユーザーに伝えてあげた方が良いと思います。

伝え方としてはいくつかの方法があります。

 

・スクロールバー

・分数表記

・矢印でスクロール可能である表示

・ちら見せ

 

スクロールバーは全体の総数が分かってさらに今この辺、という示し方ができるので最強の部類です。総数が分かって今どこ、というのが分かるという意味では分数表記もアリですが、リストタイプよりページ切り替えするタイプに向いています。簡単な表示でそんなにややこしくないのが、矢印で示すタイプ。総数が分からないのが難点ですが、小規模のリストであればデザインも軽くできてそんなに悪くないと思います。

あとはパーツを必要としない、ちら見せ。まだ先があるように一部分だけを見せます。簡単そうだけどちょっとだけ補正の計算がややこしいです。

 

というわけで、今回スクロールボックスを使わなかったので、意地でもスクロールバーに頼らない表示を実装してみます。

 

で矢印タイプを作ってみます。

まずは、矢印のテクスチャ。64x32。

f:id:hiyokosabrey:20160915012120p:plain

テクスチャ容量節約のためMaskテクスチャにします。

アルファチャンネル無しの24bitのTarga形式です。

インポート設定は以下。

f:id:hiyokosabrey:20160915012653p:plain

設定して保存したら、コンテンツブラウザのアイコン上で右クリックしてマテリアルを作成します。

f:id:hiyokosabrey:20160915012836p:plain

UMGで使用するので、Material Domain(マテリアル属性)を Surface から Use rInterface に変更します。

f:id:hiyokosabrey:20160915013346p:plain

↓↓↓ Blend Mode はOpacityを使いたいので、Translucent にします。

f:id:hiyokosabrey:20160915013359p:plain

ノードはこのようにつなぎます。

f:id:hiyokosabrey:20160915013829p:plain

マテリアルはこれで完成です。点滅させたりカラーを重ねたりしても面白いかもです。

 

前回作った『親』Widgetを編集します。

UMGで Image を2つキャンバスにレイアウトします。

f:id:hiyokosabrey:20160915014212p:plain

Detailsタブの Appearance > Brush > Image のところに作ったマテリアルをセットします。矢印は上向きしか用意していないので、下側の矢印は回転させます。

Detailsタブの、Render Transform > Transform > Angle の値を -180 にしてます。

最初は消えていてほしいので、

Detailsタブの、Behavior >VisibilityHidden にしておきます。

Widgetブループリントから触るので、IsVariableのチェックも確認。

 

編集モードをGraphに切り替えます。Event Tickにつないでいるところで空いているピンがあります。

f:id:hiyokosabrey:20160915015751p:plain

ここに矢印を出したり消したりする処理をつなぎます。

 

 表示範囲が一番上、もしくは一番下になって初めて消えて、それ以外では表示します。

f:id:hiyokosabrey:20160916001737p:plain

 配列のInde番号は 0 からスタートするので、個数を見ると、最後のIndex番号より1つ多い数字になります。(慣れないとよく混乱します)

ViewRange_Bottomも見た目の数(=ViewRange_Num)を素直に足しているので、値としては1多い状態です。こういった値を扱うとき困るのが判定部分だと思います。

f:id:hiyokosabrey:20160916052030p:plain

つなぎ方次第で同じ結果になるものもあってややこしいのですが、AとBどちらのピンを基準に考えるかがポイントです。

なので、こうなります。

f:id:hiyokosabrey:20160916045905p:plain

 今回は ==(イコール)を選びましたが、他のものでも問題なく動作させることができます。たとえば↓

f:id:hiyokosabrey:20160916053005p:plain

ViewRange_Top の値が、0 だったら Hidden(非表示)  と、

ViewRange_Top の値が、0より大きかったら Visible(表示) は同じ結果になります。

 

というわけで再生してみると

f:id:hiyokosabrey:20160916054854g:plain

 

いい感じになりました。

今回 あまり端折らないようにしようと心がけてみたのですがいかがだったでしょうか?

解らない部分などありましたらコメントいただければ、頑張ってお答えします。

ではでは

 

UMGでリストボックスを作ってみる 《続き》

 前回でリストを表示するとこまでできました。

limesode.hatenablog.com

 今回はカーソルの移動と、表示範囲の移動を作っていきます。

 

カーソルの移動とキー入力

カーソルを動かすためには、「いまここ」というのが分かっていれば

次に移動する場所が計算できます。そのための変数をInteger型で作って Event Construct ノードのすぐあとにつなぎます。FocusIndex と命名。

f:id:hiyokosabrey:20160912222408p:plain

つながなくても初期値はセットできますが、「Set」の状態で初めの方につないでおくことで、初期値が分かりやすくなるのでオススメです。

 

カーソルの移動範囲はリストアイテムの先頭から最後までです。

先頭は0で問題ないとして、最後はどうやって調べる?

数があらかじめ決まっているわけではないし。

配列に好きなだけテキストを入れる仕様なので、その自由度を尊重して、Length ノードを使います。そしてその値を保持しておく変数を用意します。

f:id:hiyokosabrey:20160912223510p:plain

 

カーソル用の変数が用意できたところで、キー入力を受け取れるようにします。

ポイントは get Player Controller ノードです。そして Was Input Key Just Pressed ノードです。

f:id:hiyokosabrey:20160912224154p:plain

Keyのところに操作したいデバイスのボタン等をセットします。上の図はキーボードのカーソルキー「↑」と「↓」です。ゲームパッドだと、D-Pad の UpとDown になります。ちなみに D-Pad の D は Directional のDなので、方向キーのことです。

ReturnValueピンが赤いので、ブーリアンで値が出てきます。True か False です。ということで Branchノードをつなぎます。さらに Event Tick ノードともつなぎます。

f:id:hiyokosabrey:20160912225102p:plain

 

キーボードとゲームパッド両方で操作したい場合は、こちらの記事を参考にしてみてください。

limesode.hatenablog.com

 それぞれのBranchノードから、変数 FocusIndex の値を プラスマイナスするようにつなぎます。

f:id:hiyokosabrey:20160912231612p:plain

VerticalBox にアイテムを追加すると、上から下に向かって足されていきます。なので上方向にカーソルを進めるには、FocusIndexの値を減らせばいいわけです。

f:id:hiyokosabrey:20160912232327p:plain

一旦増やしたり減らしてみて、範囲を越えてないかチェックします。無事範囲に収まっていれば次に進みますが、越えていれば何もしません。

越えていなければ、+1、-1した値を、FocusIndexに入れます。これで変数がカウントアップまたはダウンしたことになります。

f:id:hiyokosabrey:20160913003038p:plain

この新しくなった値で、配列に入れてある『子』Widgetのリストアイテムの関数を呼び出します。フォーカス状態にする関数です。

CreateWidgetした際に配列に積んでいった『子』WidgetをGetで指定してフォーカス状態にします。

 

この辺でテストしてみましょう。

f:id:hiyokosabrey:20160913003540p:plain

動くには動きましたが動かすたびにフォーカス状態になっていきます。

デフォルトに戻す処理を入れていないのです。

で、入れる場所は2か所。まだFocusIndexの値が更新される直前です。

f:id:hiyokosabrey:20160913003959p:plain

ゴチャついてきたので、マクロを作って差し込むことにします。setFocus関数につないだのと同じような形です。

f:id:hiyokosabrey:20160913004256p:plain

setListItemDefault という名前にしました。

f:id:hiyokosabrey:20160913004806p:plain

これでテストしてみましょう。

f:id:hiyokosabrey:20160913005000p:plain

いい感じです。

ですが、下に動かすと表示範囲の外に行ってしまいます。

 

 

表示範囲の移動

 表示範囲を越えたのかどうかを調べて、越えていれば表示範囲を動かせばいいのですが、表示範囲を管理する変数が必要です。Integer型を3つ用意します。

f:id:hiyokosabrey:20160913210845p:plain

 これを最初の方に仕込みます。仕込む場所は ↓

f:id:hiyokosabrey:20160913211211p:plain

カーソル位置をセットしている直後に仕込みます。見えている範囲はカーソルが一番上にある状態でスタートしたいからです。

f:id:hiyokosabrey:20160913211415p:plain

カーソルの位置を基準に変数の初期値を決めてセットしています。

見えている数 ViewRange_Num は見た目に見えている数を初期値として持たせています。今回は 8個見えているので、

f:id:hiyokosabrey:20160913211947p:plainとしています。

カーソルの初期位置と違って、最初から最後まで変動しないのと、デザイナの都合なのとで、特に明示しなくても誰も困らないので明示しなくていいかなと。

こういうのを「定数」とか言います。

ちなみにカーソルの初期位置については、UX的に利用する場合があるので、あえてSetノードを置いているのも理由としてはあります。カーソル位置を覚えておく場合とか。

 

変数の関係と使用イメージを図にしてみました。見えている数が5個の場合です。

f:id:hiyokosabrey:20160913220312p:plain

この4つの変数(うち1つは定数)を使って表示範囲をコントロールします。

 

 必要な変数が用意できたので、カーソルの表示範囲チェックの部分を作ります。

また差し込んでいきます。

f:id:hiyokosabrey:20160913062605p:plain

カーソル位置 FocusIndex の値が更新された直後に判定します。

f:id:hiyokosabrey:20160913222427p:plain

あともう一息。

表示範囲を動かす処理です。

同じような内容が上と下につながるのでマクロにします。ListScrollと命名しました。

f:id:hiyokosabrey:20160913223637p:plain

スクロールする方向を指定するためのパラメータ(Integer型)を受け取れるようにしています。

ではマクロの中身はこうなっています。

f:id:hiyokosabrey:20160913224601p:plain

ScrollStepというFloat型の変数を作って置いています。これはスクロール移動量で、リストアイテムの高さと同じ値が入っています。これも定数になります。

 

 VerticalBoxのポジションをGetとSetしているとこで、見慣れない状態になっていると思います。これはピンを分解している状態です。

f:id:hiyokosabrey:20160913225044p:plain

 Split Struct Pin を選択するとFloat型に分解されるのです。Breakeノードを使わないのでスッキリです。

こういった分解できるものは他にもたくさんあるので、気になったら右クリックしてみるのをオススメします。

 

テストしてみましょう。

 

f:id:hiyokosabrey:20160913225623p:plain

ようやくらしくなりました。

あとは、矢印の表示くらいですが、長くなったので今回はこの辺で。

 

 

UMGでリストボックスを作ってみる

スクロール機能のついたリストボックスを作ろうと思って、ブループリントを触り始めたら思いのほか手間取ってしまいました。当たり前のように使ってるUIのしくみって作ってみないと分らないものですね。ちょっとボリュームがあるので、うまくまとまるか自信ないけど書いていきます。

 

ちなみに

UnityとかiPhone開発界隈ではスクロールビューとか呼ばれているみたいですね。

リストボックスで検索すると、Excelの画像がたくさん出てきます。

 

今回作ってみたのはこんな感じ。

f:id:hiyokosabrey:20160911112619p:plain

UMGには ScrollBox というものが用意されていますが、今回は VerticalBox(バーティカルボックス) を使います。

 

さて、そもそものリストボックスについておさらい。

表示しきれない量の選択肢に対応するための仕組みで、表示範囲が移動するのがポイント。

f:id:hiyokosabrey:20160911123740p:plain

 

今回ゲームパッド操作を考えているので、カーソルが存在します。カーソルが移動して表示範囲を越えようとしたときにようやく表示範囲が移動します。表示範囲内であればカーソルが動いても表示範囲は動きません。

つまり、カーソル移動と表示範囲の移動は完全には連動しません。

f:id:hiyokosabrey:20160911123722p:plain

こんなとこでしょうか。

UMGでこれを再現するために、CanvasPanel で表示範囲を決めて、VerticalBox をその子供にします。VerticalBoxを動かせば、CanvasPanelの外は描画されないので、バッチリです。

 

リストアイテムを作る

 リストとして並べるパーツを作ります。

コンテンツブラウザで Add New ボタンか、右クリックで User InterfaceWidget Blueprint を選択。

f:id:hiyokosabrey:20160911125515p:plain

 とりあえず WD_ListItem命名して編集開始。

シンプルに下敷きの板(Image)とテキストブロック(TextBlock)の2パーツです。

f:id:hiyokosabrey:20160911125918p:plain

テキストブロックに が入っているのは、ディセンダ(ベースラインより下の部分。小文字の g j p q y 用)の加減が分かるようにするためです。

さらにサイズを大きめに設定して、下敷きよりも下にハミ出させているのは、VerticalBoxで並べたときにスキマを作るためです。(VerticalBoxの設定でできそうなノードを見つけたのですが、まだできないっぽい)

テキストブロックは、内容を自由に書き変えたいので、変数化します。

Detailsタブの一番上にあるチェックボックスにチェックを付けます。

チェックボックス左のフォームは変数名として使われます。

f:id:hiyokosabrey:20160911141050p:plain

 

このリストアイテムは、カーソルの乗った状態(=フォーカス)と、乗ってない状態(=デフォルト)の2つがあります。

f:id:hiyokosabrey:20160911141833p:plain

 これをアニメーションで作ります。

f:id:hiyokosabrey:20160911142304p:plain

 これで見た目は完成。編集モードを Graph に切り替えます。

さっそく関数を2つ用意します。うえの2つのアニメーションを再生するためのものです。関数にしておけば、自分以外のブループリントなどから呼び出してもらうことができます。関数は、My Blueprintタブの Functions にある +ボタンをクリックして追加します。

中身は以下のようにつなぎます。まずは setDefsult 関数。

f:id:hiyokosabrey:20160911143958p:plain

ほぼ同じ内容で setFocus 関数。

f:id:hiyokosabrey:20160911144108p:plain

両方とも同じカラーを変更するタイプのアニメーションなので、安全のためにいったん先に動いているであろうアニメーションをストップさせてから、再生するようにしています。

 

 最後にテキストブロックの内容を変える仕組みを用意します。

以前の記事では関数を使っていましたが、今回は使いません。

代わりに変数を一つ用意します。タイプはテキスト型。

EditableExpose on Spawn にチェックを付けます。

f:id:hiyokosabrey:20160911145309p:plain

 

次に Event Graph を編集します。

初めから置いてあった、Event Construct ノードに変数化したテキストブロックをつなぎます。Set Textノードは、テキストブロックのGetノードから 「set」 と 「text」 で検索するとすぐに見つかると思います。

f:id:hiyokosabrey:20160911160342p:plain

 In Textピンにさきほど作った変数を接続。右端にデフォルトアニメーションを再生する関数をつないでおきます。UMGは最後に触った状態から表示を開始する仕様なので、強制的にデフォルト状態にしておけば安心です。

 

以上でリストアイテム完成です。保存して閉じます。

 

 

 リストを並べる

作ったリストパーツを並べて表示するための『親』Widgetを作ります。

今度は WD_ListBox と名付けました。

f:id:hiyokosabrey:20160911223740p:plain

まずはUMGでパネルをレイアウトします。

f:id:hiyokosabrey:20160911223626p:plain

レイアウトしたのは3つ。

 1.下敷き(Image)

 2.表示範囲用(CanvasPanel)

 3.リスト並べ用(VerticalBox)

 

3を2の子供にします。

f:id:hiyokosabrey:20160911224215p:plain

VerticalBoxだけ太字になっているのですが、これは変数化しているという意味を表しています。ブループリントから触るのはVerticalBoxだけです。

f:id:hiyokosabrey:20160911225007p:plain

 

追記: 2020/6/27

この記事を書いていた当時、CanvasPanel はデフォルトでクリッピング(キャンバスの外側にはみ出た部分は描画しない)してくれていましたが、最近は設定が変更になったようで、今回のような表示方法では、明示的にクリッピングするよう、設定を変更する必要があります。

f:id:hiyokosabrey:20200627203131p:plain

CanvasPanel にこの Clip to Bounds を設定すると、子供にしたVerticalBox は CanvasPanelの中だけに描画されます。

<<<

 

Widget命名ルールについて、

ちょっと名前が長くなるのですが、なるべく何のパーツかわかるようにアンダースコアの前の部分は残すようにしています。

 

 

これでUMGのレイアウトは完了です。

編集モードを Graph に切り替えます。

 

まずリストパーツに表示するアイテム名を作ります。

実際にゲームなどで汎用的に使う場合、他からリストを受け取ることになると思いますが、今回はテスト用に自前で用意します。ブループリントをスッキリさせたいのと、後から取り外しがしやすいので、マクロにします。

My Blueprint > Macros  の右端にある+ボタンをクリック。

Detailsタブの下の方にある Outputs のところにテキスト型の配列を追加します。

f:id:hiyokosabrey:20160911230806p:plain

グラフのノードも変化しているので、ピンからドラッグしてMakeArray ノードを取り出します。

f:id:hiyokosabrey:20160911231002p:plain

あとは Add pin+ を好きなだけクリックして、テキストを入力していきます。

 

できたら、このマクロを使ってリストを並べる処理を作ります。

タブを マクロから Event Graph に切り替えたら、作ったばかりのマクロを取り出します。このマクロは白いピンがないので、このままだとつながりません。

そこで ForEachLoop ノードの出番です。これは配列変数と相性抜群で、とても便利なノードです。配列の要素(中身とか引き出しのイメージ)の数に合わせて処理をしてくれます。要素が尽きると Completed ピンに流れます。

f:id:hiyokosabrey:20160911232327p:plain

さらに便利なのが、ArrayElement ピンです。つないだ配列の要素を順番に取り出してくれるのです。

普通の ForLoop ノードだったらこうなります。

f:id:hiyokosabrey:20160911232811p:plain

 

Loop Body は、繰り返し行う処理をつなぐためのピンです。

ここに CreateWidget ノードをつないで 『子』の リストパーツWidget を量産します。

f:id:hiyokosabrey:20160911233809p:plain

 

Classの部分に 『子』のWidgetをセットしたとたん、ノードの下部分 に新しくピンが出現します。Expose on Spawn した変数がここに顔を出すので、ForEachLoopのArrayElementピンとつないでやります。

 

新たに『子』としてCreateWidgetされたパーツは、後から個別にデフォルトとフォーカスを切り替えるので、配列変数にしまい込んでいきます。

まず、Return Valueピンの上で右クリックして、Promote to Variable を選択します。

f:id:hiyokosabrey:20160911235105p:plain

この操作で 『子』Widget型の変数が作られます。

f:id:hiyokosabrey:20160911235301p:plain

これを配列変数に切り替えるのですが、このままやると警告が出てちょっとイヤな感じなので、いったんグラフ上で消してしまいます。Variablesリストには残っているのでそこで設定と名前を変更します。

f:id:hiyokosabrey:20160911235718p:plain

この配列変数を、Addノードを使って CreateWidgetノードとつなぎます。

f:id:hiyokosabrey:20160911235941p:plain

 

最後にVerticalBoxに追加します。Variablesリストからドラッグ&ドロップして、Getで配置したら、Add Child to VerticalBox ノードを取り出して、下図のようにつなぎます。

f:id:hiyokosabrey:20160912002801p:plain

 ループ処理が完成しました。

 

仕上げにカーソルを表現します。

ForEachLoopノードの Completed ピンに 『子』Widgetで用意した setFocus 関数をつなぎます。

f:id:hiyokosabrey:20160912003823p:plain

この辺りで一度表示を確認してみます。

レベルブループリントを編集します。

f:id:hiyokosabrey:20160912004211p:plain

再生してみると、

f:id:hiyokosabrey:20160912004355p:plain

見た目はほぼ完成です。

 

今回はこの辺までにします。

次回ひき続き動かす部分を作っていきます。

 

ではでは

 

Widgetコンポーネントにマテリアル

4.13にアップデートしてみたら、うれしい機能が追加されてた。

多分VRでWidget使いたいという声が多く寄せられたんじゃないかと想像してみたり。

Widgetはそのままだと、2Dだけど、とWidgetコンポーネントとしてWorld空間に置くと3次元が表示できる。DeadSpaceが再現できる。

ブループリントアクターから、Widgetコンポーネント としてビューポートに追加するんだけど、4.13からここにマテリアルがセットできるようになった!

f:id:hiyokosabrey:20160904211101p:plain

相変わらず Experimental(実験的)実装なまま・・・

 

マテリアル以外にも気になるパラメータがあるんだけど、とりあえずマテリアルで実験してみた。

適当な背景用画像を用意。

f:id:hiyokosabrey:20160904213625p:plain

で、これを使ってマテリアルを作成。SceneDepthを利用。

f:id:hiyokosabrey:20160904213710p:plain

Widgetに使うんだけど、コンポーネント用だとマテリアルドメイン(属性)は Surfaceでいいみたい。

ScreenDepth は、不透明モデルが描画されるタイミングで更新されるぽくて、そのDepth(深度)情報を元に if ノードで描くか描かないかを決めています。

 

次に、Widgetブループリントを作成。

といっても、上のマテリアルで適応するとWidget自身の描画がされないので、ひとまず四角い板を一つ。

f:id:hiyokosabrey:20160904214740p:plain

サイズは 適当に 1920x1080 。

SaveしてWidget完成。

 

次にブループリントアクターを作成します。

+Add Component ボタンから、Widgetコンポーネントを追加します。

f:id:hiyokosabrey:20160904215126p:plain

追加したら、エディタ右の Detailsタブを確認して、

Material という項目を探して用意したマテリアルをセット、

f:id:hiyokosabrey:20160904223631p:plain

すぐ下の User Interface という項目の、Widget Class に作ったWidgeブループリントをセットします。

f:id:hiyokosabrey:20160904215925p:plain

Draw Size に描画したい大きさを指定できるのですが、Widgetの中身に合わせてほしいので、Draw at Desired Sizeにチェックを付けておきます。

簡単なテストなんでブループリントはこのくらいで出来上がりです。

 

ではワールドに配置していきましょう。

適当なキューブとかスフィア(球)を置きます。ライトも適当に。

ブループリントもドラッグして配置します。右端がブループリントの中にいるWidgetコンポーネント

f:id:hiyokosabrey:20160904224930p:plain

これをWidget側に回り込むと・・・

f:id:hiyokosabrey:20160904225143p:plain

手前にいるのに、モデルより奥に描画されています。SceneDepth情報がうまく利用できているということです。

カメラに貼り付けたりビルボード的に表示できれば面白い使い方ができそうです。

 

4.13いいですね。

まだまだ検証しないといけないですが、また何か発見があれば記事を書こうと思います。

 

今回はこの辺で。

 

 

 

 

 

 

 

UIを作ることの難しさ

f:id:hiyokosabrey:20160828153229p:plain

UIを構成するのはデザインだと思っている人がいる。デザインなんてほんの1割程度だということを理解している方はどのくらいいるのだろうか?

 

UIは目で見て操作するタイプが多いので、見た目に誤解を招いたり、スムーズなオペレーションに誘導できない場合は、デザインやインタラクションで解決することになる。

機能要件を実装するためにロジックを組み上げ、ユーザー体験というストーリーボードを想像しながら、時間をかけて作り上げていく。

 

そこに「クオリティ」や「イメージ」をという名の武器で斬り込んで切る方がいる。

その「クオリティ」や「イメージ」で斬られたものが悪いもの(BAD UI)であれば良くなるのだけど、一方的な押し付けに近いなまくらで斬られると痛い上にロジックが破たんするので、立て直しに時間がかかる。

デザインを変えただけではうまくいかない。

 

ゲームのUIを作るという仕事は、庭を作るのに似ているように思う。

でもUIをデザインだと考えているひとは今すぐ花を用意して飾ればいいと言う。その飾り方にコダワレと言う。確かにその方が短期間でいい見栄えのする状態にすることはできる。切り花の展覧会ではないので、枯れたらおしまいというわけにはいかない。毎日その庭を眺めることになるのを踏まえて、飽きのこない手入れが少なくてもいい植生を考えることになる。でもそれを納得しない人がいるのも事実。

ゲームを起動して終了するまで、または一つのモードを何度も遊ぶようなプレイサイクルを考えると、UIはプレイヤーをストレスなく導くものであってプレイサイクルをジャマをしてはいけない。あくまでもUIは影の主役であって表に出てはいけない。


少し話は変わって、

家の敷地の角でよく見かけるナンテンの木について詳しく知っているひとは少ない。なにも知らなくても赤い実がキレイだなくらいの視覚効果はある。赤い実のなる木はいくらでもあるのに、なぜにナンテンなのか。そこにロジックが存在する。その理由を知らないで何かを植える話になった場合いくつかの選択肢が出てくると思う。

・なんかあちこちの家でナンテンを植えてるみたいだからナンテンでいいよ。

・赤い実よりもサザンカやツバキみたいな花がいい。

・いつでも実や花があるわけではないから一番キレイな状態の造花がいい。

・そもそも植える必要はあるの?何か別のオブジェを置いたら?

 

とまぁこんな感じで話をまとめるのに苦労しそうな予感しかしない。

実際ナンテンには微量の毒があって虫除け効果がある。赤飯なんかに葉が載せられているのはそのため。鳥も一度にたくさんは食べない。その方がフンが拡散するから。漢方薬にもなっていたり、名前の由来は「難を転じる」からとか、雪ウサギの耳に使う1枚の葉は、実はあれで1枚ではなく、100枚近くある小葉全体で1枚の葉だったり、調べてみると面白い話がいっぱい出てくる。

 

とまぁ、なんか文字ばっかり、理屈ばっかりになったけど、ちょっと憂さ晴らししたくなったのでこの場を借りて書き散らしてみた。もっといっぱい書きたいことがあるのだけど愚痴にしか聞こえないだろうからこの辺にしておきます。

明日から頑張ろう。

 

 

UMGのフォントをアレンジ

f:id:hiyokosabrey:20160827205227p:plain

UE4で扱えるフォントは大きく分けて2種類あります。これは実装方法によって分けられています。ひとつは Runtime(ランタイム)と呼ばれるもので、これはTrueTypeFontやOpenTypeFontでおなじみのアウトライン情報をメモリに埋め込んで利用します。文字の量が膨大になっても容量は少なくて済み、またどんなサイズでもキレイに表示できるのでコスパ的にセリフや字幕、説明用のテキスト表示に最適です。

もう一つが、Offline (オフライン)と呼ばれているもので、これは昔からある手法で、文字をラスタライズ(ビットマップ化)してテクスチャにします。後からPhotoshopなどでドット修正できたりフチドリやエフェクトを乗せることができるので使い勝手がいいのですが、最大の欠点は、文字サイズが固定なのと、文字量が増えるとテクスチャ容量が大変なことになるという点です。最近の多言語対応や、テキストチャットなど考えると、漢字だけでも20,000文字越えるので、Runtime のありがたみをしみじみと味わっている今日この頃です。

 

さてさて

現状 UMGで扱うことのできるフォントは、Runtime(ランタイムフォント)しか使えないようですので、今回はこのランタイムの文字で遊んでみました。

このランタイムフォントは、ラスタライズされていない状態でメモリに載っているので、テクスチャのよう加工方法が使えません。テキストブロックをビューポートに描いた時点ではじめてラスタライズされるからです。えー じゃぁグラデーションは?

ということでDetailsタブをいろいろ調べてみると、どうやらマテリアルが使えるようです。ニヤリ。

 

まず↓のようなテキストブロックをキャンバスに置きます。

f:id:hiyokosabrey:20160827205325p:plain

UMGでは斜体が簡単に掛けられるのでイイですよね。

で、マテリアルを作るのですがその前にテクスチャを2枚。

f:id:hiyokosabrey:20160827205933p:plain  16x128 の24bit Targa

f:id:hiyokosabrey:20160827205939p:plain  64x64 24bit Targa

それぞれインポートします。

64x64の方は Opacity につなぐので、sRGBを切って Grayscale(sRGBを切るとマテリアル内ではLinearGrayscale) にします。

このテクスチャを使ってマテリアルを作っていきます。

f:id:hiyokosabrey:20160827210658p:plain

緑のノードは、ScalarParameterValue ノードです。 ブループリントから触れるようにしたり、マテリアルインスタンスから触れるようにするためのノードです。 とりあえずパラメータ名 を "param" にしました。パラメータ名をセットすると、ノード名のように表示されます。フェードインすさせるので初期値は 0.0 がいいのですが、このあと作業しづらいので、いったん 1.0 にしておきます。

UMGで使うので、右端のマテリアルドメイン(マテリアル属性)はUser Interface を選択します。

マテリアル完成です。Apply してSaveしたらウィンドウを閉じてOK。

 

ここでUMGに戻って、さっきキャンバスに置いたテキストブロックにセットします。

エディタウィンドウ右のDetailsタブにある Appearance > Font の中です。

f:id:hiyokosabrey:20160827205720p:plain

このままでは何も変化しないので、アニメーションを作ります。

適当にこのテキストブロックがフェードインしてくるのを用意します。

f:id:hiyokosabrey:20160827211828p:plain

1秒かけてアルファを 0.0 から 1.0に 上げています。

このアニメーションを再生するようにします。

エディタをGraphモードにして、Event Construct ノードにつなぎます。

f:id:hiyokosabrey:20160827212208p:plain

Event Construct ノードはビューポートに描かれたタイミングで処理が流れてくるイベントです。

この辺で、いったんコンパイルして保存します。

レベルブループリントで以下のようにノードをつなぎます。

Create Widget ノード に Add to Viewport ノードです。Class のところに上で作ったWidgetをセットします。

f:id:hiyokosabrey:20160827212848p:plain

Playして確認してみると、

f:id:hiyokosabrey:20160827220106g:plain

まぁフツーですね。

このアルファを使ったフェードインを、マテリアルに仕込んだパラメータに渡します。

 以前にこの方法を紹介していたので貼っておきます。

limesode.hatenablog.com

マテリアルを操作するためには DynamicMaterial を作ってやる必要があります。過去記事では Image パーツから Get Dynamic Materialノードで進めていますが、同じ方法で テキストブロックのマテリアルからDynamicMaterialが作れないことが判明。困った。

・・・

イロイロ調べた結果、なんとかその方法が見つかりました。

まずブループリント(Widget以外)でやるのと同じように、先に Create Dynamic Material Instance します。(Play Animationノードはひとまず除けておきます)

f:id:hiyokosabrey:20160827221931p:plain

Parent のところにUMG用に作ったマテリアルをセットしておきます。

キャンバスに置いたテキストブロックは変数化して使うので、Designerモードで Is Variableのチェックボックスにチェックを付けます。

f:id:hiyokosabrey:20160827223006p:plain

再び編集モードをGraphに戻すと、テキストブロックがエディタ左の Variables の中に並んでいるはずです。これをグラフにドラッグ&ドロップします。

そこから、下のようにノードをつないでいきます。出力ピンからドラッグして、"get font" とか、"break" 、"make" とかで検索すると速く見つけられます。

f:id:hiyokosabrey:20160827223420p:plain

これで、ようやくテキストブロックに Dynamic Material が、セットできました。

最後に、よけておいたPlay Animatonノードをつないでやります。

f:id:hiyokosabrey:20160827224545p:plain

Event Construct はこれで完成。

次に Event Tickです。

アニメーションのアルファ値を拾ってDynamicMaterialに渡します。

f:id:hiyokosabrey:20160827224640p:plain

 なぜか Get Color and Opacity ノードから、直接 Break LinearColor ノードが取り出せないので、いったん Break SlateColor しています。

 

完成です。

再生してみましょう。

f:id:hiyokosabrey:20160827230323g:plain

Opacityのアニメーションを改造すると、もっといろんなバリエーションが楽しめそうです。

 

グラデーションもテクスチャを使わない方法があります。

f:id:hiyokosabrey:20160827230651p:plain

 

UMGのRuntimeフォントをアレンジできれば結構オリジナリティも出せて、リッチに見えるので、ネタを思いついたらまた紹介しようと思います。

 

ではでは

今回はこの辺で

 

マテリアルで目パチ

キャラ絵の目パチ(まばたき)は口パクのようにセリフと連動することはありませんが、キャラが生きていることを表現するために必要な演出です。

その目パチの間隔をランダムで制御しようとするとそれなりにノードを組む必要があります。かといってタイムラインで制御しようとすると、他のアニメーションとバッティングするかもしれません。特に制御する必要がないけどそれなりに動いていてほしいのが目パチです。

そこで、マテリアルを使って目パチアニメーションを仕込んでみます。

 

まず2枚のテクスチャを用意します。

f:id:hiyokosabrey:20160821203425p:plain   f:id:hiyokosabrey:20160821203431p:plain

ほんとは動く部分だけを切り出して重ねた方がいいのですが、位置合わせが面倒だったのでちょっと贅沢な作りでいきます。

 

つぎにタイムラインに相当するテクスチャを用意します。

f:id:hiyokosabrey:20160821203805p:plain

128x8 のMaskテクスチャです。白と黒の2色のみです。

小さくても十分なので、キャラ絵のテクスチャにすき間があったらそこに入れることでキャラ固有のパターンが用意できますが、今回は別テクスチャにしています。

 

白黒2階調のテクスチャなので、フォーマットをMaskにします。

最初に Photoshopで 24bit の Targa形式で書き出して、インポート設定を以下のようにします。設定を変更したら Reimport ボタンを押してから Save します。

f:id:hiyokosabrey:20160821204613p:plain

 

テクスチャが用意できたのでマテリアルを作ります。

コンテンツブラウザから、3つのテクスチャノードをドラッグ&ドロップして並べます。それぞれを if ノードにつなぎます。

f:id:hiyokosabrey:20160821205303p:plain

次にアニメーションさせるために Panner ノードとサイズを調整する Tex Coordinate ノードをつなぎます。

f:id:hiyokosabrey:20160821205744p:plain

マスクテクスチャの解像度と白い部分の幅とでベストな値が変わります。

 

もうひとつ、if ノードの Bのピンにつなぐために  Constant ノードを用意します。

数字の1キーを押しながらクリックすると取り出せます。とりあえず 0.5 としておきます。

f:id:hiyokosabrey:20160821210248p:plain

では合体!

f:id:hiyokosabrey:20160821210423p:plain

完成です。

f:id:hiyokosabrey:20160821211913g:plain

 

 

マスクテクスチャの白い部分の間隔をいじればタイミングが調整できます。

f:id:hiyokosabrey:20160821203805p:plain

これも一つのタイムラインです。

テクスチャなんで容量は無駄に食いますが、プログラム的にややこしいことを一切していないのと、デザイナーが調整しやすいことがメリットではないでしょうか。

 

あと、if ノードのピンが1つ空いているので、もう1枚 絵入れて3パターンにすることもできます。

 

ではでは

今回はこの辺で