みつまめ杏仁

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

UE4のテキスト効果

相変わらず記事を書く時間が取れないまま4月ですよ。ニューカマー達が押し寄せてきてます。すぐそこに!

というわけで、ぷちネタを思いついたので、書いておきます。

もう誰かがやってそうですが・・・・

なんとUE4の最新バージョンで

Widgetのテキストブロックに、ソフトなドロップシャドウが! さらにグロー処理も!

f:id:hiyokosabrey:20170409015154p:plain

 

 

・・・

実はこれ、エイプリルフール向けのネタとして準備していたものです。

種明かしをすると、Ver 4.15から実装された、Background Blur パネル を使用しています。

シャドウとグロー用のテキストブロックを置きます。

f:id:hiyokosabrey:20170409020510p:plain

そこに Background Blurパネルを重ねます。

f:id:hiyokosabrey:20170409020518p:plain

仕上げにテキストブロックを重ねて完成です。

f:id:hiyokosabrey:20170409015154p:plain

大したネタではないですね。すみません。

 

この方法はあくまでも背景がシンプルな単色だからできる方法です。

テクスチャで表現する方法だと、テキストの変更に合わせるのは大変です。

使いどころは限られますが、うまく使える場面はきっとあると思います。

 

今回は短いですがそろそろ寝ます。

ではでは

ステキなWidgetライフを!

 

 

はみ出た文字のサイズを調整

本記事は2017/3/21にアップした内容に、2018/8/6に加筆修正した内容になります。

 

久しぶりの更新。なかなか記事を書く時間がないので困ったものです。

NintendoSwitchにもUE4が対応するということで、どんなゲームUIが出てくるか楽しみです。

さてさて以前テキストに合わせてフキダシの大きさを変えるのを書きましたが、今回は逆に決められたサイズを越えたら無理やり収めるというのを書いてみようかと。

UMGのテキストブロックには、Size to Content という設定があって、これを有効にすると中身に合わせてサイズが可変するというしくみが用意されています。

f:id:hiyokosabrey:20170319020555p:plain

 

まずはSize To Content にチェックを付けたテキストブロックを3つ並べてみます。

f:id:hiyokosabrey:20170319020110p:plain

 

簡単かつ確実に中央揃えにするために、アンカーは、3つともCenter Top。

f:id:hiyokosabrey:20180805220724p:plain

さらにAlignment の値も3つとも X を 0.5 にします。

f:id:hiyokosabrey:20180805221747p:plain

あと、Position X も 0.0 にすると、特に計算しなくても中央揃えになってくれます。

 

まとめると、横方向に中央揃えにする場合、以下の3か所をセットすればOK。

f:id:hiyokosabrey:20180806204859p:plain

この組み合わせで、確実に中央揃えにできます。

親のキャンバスパネルのサイズを変えても、きちんと追随します。

 

Alignment で指定した位置が、そのパーツの基準位置ということになります。

そして、Anchorsの基準位置から 「どれだけ離すか」というのが、Positionの値になるので、結果として、中央揃えになります。

 

 

配置ができたので、ブループリントから文字を流し込んでみます。

SetTextノードを使います。

f:id:hiyokosabrey:20170319021924p:plain

単品だと↑のようなカタチになりますが、3つのTextBlockにまとめて流し込むには、まずTextBlockを配列型にします。MakeArrayノードから作る方法をご紹介します。

f:id:hiyokosabrey:20180805213830p:plain Add pin をクリックして [2] まで増やします。

そこへ TextBlockをつないでいきます。

TextBlockは IsVariable にチェックを付けると、変数として扱うことができます。

Getの形で接続。

f:id:hiyokosabrey:20180805213911p:plain

最後に、Array ピンの上で右クリックして、Promote to Variable を選択すると、

f:id:hiyokosabrey:20180805213954p:plain

TextBock型の配列が出来上がります。

 

この配列に対して ForEach Loop ノードを使えばすべてのTextBlockにアクセスできます。

f:id:hiyokosabrey:20180805220415p:plain

適当な文字を仕込んでPlayしてみると・・・

f:id:hiyokosabrey:20180805222147p:plain

3つとも一度に書き換わります。

 

では長さの違うテキストを表示してみます。

準備として、テキスト型の配列を用意します。

実際のゲームでは値を受け取って表示する流れになりますが、ここでは実験なので、このブループリント内で、用意します。

テキスト型の配列変数をあらかじめ作っておいて、Setの形で配置します。

そこへ、Make Array ノードをつないで、Add pinすると、いくつもテキストを入力することができます。

とりあえず大好きなゲームから拝借。

f:id:hiyokosabrey:20180806210927p:plain

これを、先のForEachLoopで利用します。

f:id:hiyokosabrey:20180806211515p:plain

 

再生してみます。

f:id:hiyokosabrey:20170321005407p:plain

みごとに2つ目がサイズオーバーです。

これを、はみ出たやつだけ縮小するようにします。

 

はみ出た場合に縮小する関数はこんな感じ。textSizeAdjust と命名。

f:id:hiyokosabrey:20180806214214p:plain

関数が受け取る値(Inputs)のピンは2つ、TextBlock型と、Float型です。

 

この関数を、ForEachLoop でループ処理している最後の部分につなぎます。

f:id:hiyokosabrey:20180806214342p:plain

関数に渡している MaxWidth の 230 は、縮小するかしないかを判定するためのしきい値になります。

f:id:hiyokosabrey:20180806213717p:plain

 

でPlayしてみると・・・

f:id:hiyokosabrey:20170321010914p:plain

いい感じに収まってくれました。

 

フォントの形がおかしくなるので、あまりやらない方がいいのですが、

表示したいテキストのうち、ほんの少しくらいならこういった縮小処理は画面レイアウトを維持するためには積極的に使っていきたいものです。

 

ではでは今回はこの辺で

ステキなTextBlockライフを!

 

 

再編集にあたって

先日コメントを頂いて、改めて記事を見てみると余計な情報はあるわ、Alignmentの使い方分かってないわで、大変申し訳ない気持ちになった次第で、表題通りにバッサリと整理しました。

計算してセンタリングできるという方法を披露したかったのだと、当時に思いを馳せてみたのですが、「はみ出た文字サイズを調整」というタイトルと合ってない印象はどうしようもないので、内容の再編集に踏み切りました。

 

 

 

 

テキストブロックのスクロール 続き

前回の続きでスクロールバーを付けてみます。

limesode.hatenablog.com

 以外にサクッとできました。まずはUMGのパーツを追加するところから。

 

f:id:hiyokosabrey:20170220223725p:plain

スクロールバー全体の大きさを決めるキャンバスパネルを親にして、スクロールバーの下敷きとバー本体を表すImageパーツを子供にします。ちょっとだけラクをしたいのでバーの長さは、テキストブロックの表示サイズと同じにしています。

 

スクロールバーの長さを計算して変更する関数を追加します。

f:id:hiyokosabrey:20170220224608p:plain

このセットアップ関数は、テキストブロックの中身を変更する関数の中に置きます。

f:id:hiyokosabrey:20170220224816p:plain

スクロールバーを動かすためのマクロを用意。

f:id:hiyokosabrey:20170220225243p:plain

これをテキストボックスのスクロール部分にくっつけます。

f:id:hiyokosabrey:20170220230103p:plain

テキストボックスを動かす計算をしたあと、その値を拝借するカタチです。

以上で完成です。

 

不思議の国のアリス(英語)の冒頭を使って試してみました。

f:id:hiyokosabrey:20170220230446p:plain

f:id:hiyokosabrey:20170220230458p:plain

やっぱりスクロールバーはいいですね。あとどのくらいっていうのが判るのは大事です。

UMGにはとても便利な 『スクロールボックス』 が既に用意されているので、わざわざ苦労して作ることもないのですが・・・ こういった基本的なUIを自分の手で一回は作っておくのもいいと思います。試行錯誤してみて初めて仕組みの深いところが分かったり、当たり前のように毎日使ってるGUIの奥深さに気付くこともあるかと。

 

ではでは今回はこの辺で

ステキなスクロールライフを!

 

 

テキストブロックのスクロール

f:id:hiyokosabrey:20170218200852p:plain

 テキストブロックで、長文を表示しようとしたときに、たいていAuto Wrap Text(=自動改行)にすると思います。

f:id:hiyokosabrey:20170218203113p:plain

文字量が多いとサイズが大きくて表示しきれないので、スクロールさせるのが我々UI業界では当たり前の仕組みです。

 

UMG パーツ

f:id:hiyokosabrey:20170218220855p:plain

 まずはイイ感じの大きさのキャンバスパネルを置いて、その子供にテキストブロックとイメージを配置します。キャンバスは表示範囲を限定するためのものです。子供たちにとってこのキャンバスパネルが実際に表示される大きさになるので、アンカーの設定を右下のやつに設定します。

f:id:hiyokosabrey:20170218221511p:plain

スロットの設定は以下のようにすると、親のキャンバスパネルにピッタリフィットするように可変します。

f:id:hiyokosabrey:20170218221818p:plain

 Offset ~ は余白が欲しい時に設定します。

 

Event Construct

事前に取得できて後から再利用できる値は、なるべく変数化しておきます。

f:id:hiyokosabrey:20170219223957p:plain

 ここでは、見える範囲と一度にスクロールする量を求めて変数にしています。

 

 テキストブロックの中身を変える

 UMGのテキストブロックには、内容を変更する方法が3つ(他にもあるかも)用意されています。

1.テキスト型の変数に直接バインドしてしまう方法Flashみたいな)

  その変数の内容を書き換えるだけで反映されます

2.関数にバインド(紐づけ)して、その関数の戻り値を使う方法

  その関数にパラメータ(引数)を渡していろいろ加工することができる

3.バインドせずに setText ノードを使う

  エンジンが値を見張ることがないので処理の負担が軽い

 

頻繁に値が変わる場合は、1か2が向いていますが、今回作ろうと思っているのは内容がほとんど書き換わらないので、3にします。

↓テキストをもらって書き換える関数です。

f:id:hiyokosabrey:20170218224228p:plain

 ForceLayoutPrepassノードと getDesireSizeノードのコンビネーションで新しいテキストブロックのサイズを取得します。右端の関数は、親のキャンバスパネルのサイズと比較してスクロールするかどうかをチェックする関数です。キャンバスパネルに収まらなかった場合のみスクロールできるようにしたいので比較してフラグを立てます。

f:id:hiyokosabrey:20170219223606p:plain

ついでにスクロールの限界位置を計算して変数に入れておきます。

 

フラグが立ったら

 フラグといってもブーリアン型の変数です。それをEventTick に Branchノードでつないでやります。スクロールが必要ない場合は処理を省けます。

スクロールが必要な場合は、キー入力を受けてスクロール処理をします。

f:id:hiyokosabrey:20170219225459p:plain

入力チェックのマクロはこんな感じ。

f:id:hiyokosabrey:20170218233113p:plain

Was Input Key Just Pressed ノードは、EventTickのように細かく処理が流れてくるところにつないで使います。Get Player Controller ノードがないと使えないので注意。

ゲームパッドとキーボードのカーソルキーを両方扱えるようにしたいので、OR(論理和)ノードで判定してます。

関数は出口が一つだけど、マクロだと分岐できるのでこういった場合とても便利です。

スクロールするために用意した関数は3つ。スクロール量を計算する関数2つと、実際に動かすための関数になります。

f:id:hiyokosabrey:20170219230322p:plain

f:id:hiyokosabrey:20170219230331p:plain

最終的に、青いノード(Vector2D)に移動後の値(目的地)が入るようにします。

キー入力のたびに上の関数が呼ばれ目的地が瞬時にセットされます。で、常時処理されるのがこの関数↓

f:id:hiyokosabrey:20170219230803p:plain

目的地から現在地の差分に0.1を掛けて現在地に加算したものを新しいポジションとしてセットします。これで常に目的地に向かって移動し続けます。0.1は速度の調整用として掛けています。

 

完成

f:id:hiyokosabrey:20170219231224p:plain

 試しに、シャーロックホームズの冒険(英語)から”ボヘミアの醜聞” の冒頭を流してみました。いい感じにスクロールできます。フォントは Canterburyという書体です。

f:id:hiyokosabrey:20170219231545p:plain

 無事ちゃんと動いていますが、まだ先があるのかわからないので、UIとしてはまだ完全ではないです。スクロールバーか、▼表示か、好みが分かれるところです。あと、上下の端に辿り着いたときに、ループさせるか否かも悩ましいところです。ということで今回はこの辺にしておきます。

ではでは

ステキなスクロールライフを

 

【おまけ】小数点でハマった

最初1行ずつスクロールしていたのですが、行数が多くなると誤差が出てきたり、端までいったときの判定が難しかったりで、結局 固定のスクロール量にしました。それほど悪くないと思います。同じ値を足し引きしてるはずなのに、数値が 0.0000008 みたいなことになるので、< >を使った判定が思うようにいかず頭をかかえることに・・・

 

【補足】うまくgetDesireSizeで取得できない場合

 まだ原因がよくわかっていないのですが、UMGの編集を開始してからしばらくはタイミングによってはまったくサイズが取得できなかったり、改行する前のサイズが取れてしまうようです(私の環境のせい?)。

 そこで確実に改行後のテキストブロックのサイズが取れる仕組みを見つけようといろいろ接続を試してみました。EventTickにつないでチェックすると間違いなく取れます。

f:id:hiyokosabrey:20170218215800p:plain

 DoOnceノードを使って処理をしたりしなかったりをスイッチングします。

 (このあたりいじってたら、いつのまにか、なくても取得できるようになってました・・・)

 

 

UMGでよくやらかすやつ

最近カレンダーを見るのが怖い。

年が明け、あっという間に1月も残り1週とちょっと。ブログの更新もペースが落ちて前回から随分間が開いてしまいました。世間から忘れ去られないように頑張っていきたいと気合だけは入れているのですが・・・

 

 さてさて、今でこそ注意するように習慣ができてきたのですが、UMGでアニメーションを作っていて、いざ見てみようと再生すると、「え?」という状況によくなります。最初は原因が分からないので、エンジンの不具合か?などと人のせいにしたりして、「UMGワケわかんな~い。」とか聞こえないのをいいことにぷつぷつとぼやいていたものです。

 原因が分かれば怖くないのですが、これが原因でUMGをキライになる人が増えるのは不幸なのでメモ程度に書いておこうと思った次第です。

 必ず起こるわけではないのですが、起こりやすいのが、フェードやフレームIN/OUTのように最初は見えない系。このタイプのWidgetを表示したときに、一瞬だけ変なタイミングのアニメーションが再生されることはないですか?その解決策をご紹介します。

 

 普通にWidgetブループリントを作って、UMGのタイムラインでアニメーションを作って完成したらコンパイルして保存すると思います。このとき必ず儀式というかお作法のようにやった方がいいのが、アニメーショントラックリストのフォーカス外しです。

 アニメーションを作って確認していると、アニメーショントラックリストがフォーカスした状態になっています。このフォーカスを外してから保存することがとても重要なのです。

f:id:hiyokosabrey:20170122211605p:plain

(外すとオレンジ色の帯が消える)f:id:hiyokosabrey:20170122211811p:plain

この地味な操作は、アニメーションが一切再生されていない状態、つまりUMGのデフォルト状態を確認するためです。このデフォルト状態の確認を怠ると、Add to Viewportしたタイミングで「!」となるのです。

  デフォルトの状態と、最初に再生するアニメーションの0フレーム目が同じ状態ならバッチリなのです。

 

 フレームインだと画面外、フェードインだと完全に透明、というのがデフォルト状態になるので、レイアウト作業がしづらいです。そこでポジションを動かしていたり、アルファの値を 0以上にしていたりするのですが、そのまま保存して確認、「!」というパターンからなかなか抜け出せない自分に若干イラっとすることに・・・

そこで『フォーカス外し』なのです。すこしの手間ですが、これを習慣づけることでストレスは減った気がします。この操作でシステム的に解決するわけではないので、期待された方がいたらゴメンなさい。確認は自分の目でします。

 

ではでは

今年もよろしくお願いします。

ステキなUMGライフを!

 

 

 

 

アンリアルエンジン4を使いながら

 このブログも始めてから1年経ちました。どーせすぐ飽きるかなと思ってたけど、なんとか続けることができて今更ながら自分に驚いてます。これも素晴らしいエンジンに出会えたからに他ならなくて、ゲームユーザーインターフェイスの制作で少しでもお役に立るなら、アンリアルエンジンをステキなUI制作ツールとして周知させることができるんじゃないかという野望というか下心が原動力になっている気がします。

 

 実際デザイナーという肩書で、「UIの絵素材」を作り、エンジニアにこのパーツはこう動かして・・・これはこの時はこうなってて・・・まだ非表示で・・・UVが・・・。みたいな指示書や資料を作ってお願いしていたのが、UE4の登場で変わりました。

 

 UIデザインの仕事って軽く見られている気がするのは、単なる被害妄想ではないと思いたいのですが、画面に表示されるゲージなんて四角い選択範囲を塗りつぶしただけでできそうだし、数字なんてフォントを適当な位置に置いてるだけで、制御してるのはプログラムのおかげだし、配置やカラーにどんな意味やロジックが込められていようと見た目にカッコ悪いと、UIダサいとか言われるし・・・この辺のモヤモヤを一気に吹き飛ばしてくれたのがUE4です。

 

 まずは作ってみる。試してみる。最初はノードが怖くて変なつなぎ方したらヤバいことになるんじゃ・・・とビビリながらつないでました。多少はお作法みたいなものを身に付ける必要はあるけど、白い線をたどってノードを順番に追っていきながらアーでもないコーでもないと、今では作りたいUIはなんとかなる。というくらいの自信はつきました。

 ようやく書き上げた指示書を渡して、エンジニアに動かしてもらって「なんかヘン」って時に調整に付き合ってもらえるとありがたいんだけど、忙しい時期だと修正を頼むのも心苦しい。

 UE4だと、まずは自分でどうにかして狙った動作(プロトタイプ)を作ります。それを評価してもらって仕様に合ってない部分を確認したり、拡張性について共有しながら、ブラッシュアップします。アセットの管理についてはエンジニアのアドバイスをもらいながら準備を進めていきます。このとき作ったものを壊す勇気は必要です。作り直すときに新しい方法に気付くことがあります。

 

 GUI は様々なステータスや値をグラフィカルに表示し、ユーザーに視覚情報として伝える役割があります。その表示のためのステータスや数値の扱いはエンジニアと相談して受け取り方を決めます。デザイナーはその値をもとに「伝え方(見せ方)」をデザインするのです。

 こうしてできたモックアップは動く指示書としてエンジニアに渡せます。ゲームの部品として組み込んでもらってようやくひと段落です。あとは見た目や統一感などバランス調整をして仕上げていきます。

 今までは、ややこしいアニメーションや演出のタイミングの制御をエンジニアが引き受けてくれていたので、割とバグとは無縁でいられたけどUE4でできるとなると、デザイナが引き受ける流れに自然となります。面倒な指示書、頼みにくい調整が無くなった分、見た目の不具合については責任として乗っかってくる感じです。

 

 UE4はUIを開発するのに向いていると思います。手法を思いつくまでは悩むことも多いけど、大抵のインタラクションを作ることができるので、理想のUIを構築できる環境はすべて揃っていると今でも信させてくれています。ここまでフトコロの深いツールは他にないんじゃないでしょうか。まだまだ進化しそうなUMG。正直手放したくないです。世界中のUIデザイナーが「UE4で作らせろ」って声を上げてくれる日を夢見てこのブログも頑張って続けていこうと思う今日この頃です。

 EpicのUE4開発チームの皆様ありがとう。そして来年もよろしくお願いします。

 というわけで今年もあと1日。当ブログを見に来ていただいた皆様ありがとうございます。更新ペースは遅いですが、来年もよろしくお願いします。

 

ではでは

ステキはUE4ライフを!

 

f:id:hiyokosabrey:20161230235018p:plain

 

 

 

ストラクチャを使ってみる

前にEnum(いーなむ)を使ったリストメニューについて書きましたが、最近になってUser Defind Structureが便利なことに気付きました。

ストラクチャはプログラム界では《構造体》とか呼ばれているようで、Enumと同じように、アセットで管理できます。Enumと違って中にいくつでも変数を仕込むことができるので、使い方によっては、とても頼もしい存在になってくれそうです。

 

作り方は簡単。コンテンツブラウザからいつも通り右クリックして作れます。

f:id:hiyokosabrey:20161214012219p:plain

 

で生まれたのが下のアイコン。

f:id:hiyokosabrey:20161214012242p:plain

コンテンツアイコンには、New User Defined Structure とあります。

「新しくユーザーが定義した構造体」ということになるのでしょうか。

いい感じの名前を付けたら、編集ウィンドウを開いて、変数を追加していきます。

f:id:hiyokosabrey:20161215000309p:plain

上の例ではText型の配列変数を一つ追加しました。

Saveして閉じたら、このストラクチャを使おうとしているブループリントを開きます。

そこで変数を追加します。

変数を追加したら、型(VaribleType)を変更するのですが、リストの中に自分の作ったストラクチャが追加されているはずなので、それに変更します。

f:id:hiyokosabrey:20161216003656p:plain

下図はストラクチャの名前と変数名を "ListName" にした場合です。

f:id:hiyokosabrey:20161216003945p:plain

 

値を取り出す場合は、Breakノードを使います。

f:id:hiyokosabrey:20161215030933p:plain

ストラクチャだと配列が扱えるので、値を取り出すのも簡単。ForEachLoopとの連携も便利です。

 

他にもいろんな型の変数が扱えるので、マテリアルパラメータコレクションみたいな使い方も便利そうです。アセットなので、カラーを初期値として設定しておけば、いろんなブループリントで共有することができるので、カラールールを揃えるのも簡単。一斉に修正や調整ができて便利そうです。

f:id:hiyokosabrey:20161216005354p:plain

 

変数として扱えるということは、当然、値をセットすることもできます。

その場合、Makeノードを使います。

f:id:hiyokosabrey:20161223234728p:plain

アセットの中身が書き換わるわけではないので、普段の変数と同じように扱えばOK。ただ、SetとGet のカタチで直接触れないので、BreakとMakeノードの助けを借ります。

 

なんとなく便利そうなストラクチャですが、ちょっとだけ気を付けることがあります。

ストラクチャのアセットを編集すると、そのストラクチャを使用しているブループリントすべてが自動的にコンパイルされ、未保存の状態になってしまいます。新たに別のレベルを開くか、エンジンを終了しようとすると、ダイアログが出てきて保存するかどうか訊いてくるので、うっかりDon't Save を選ばないように。

 

そんなに使いどころは無いかもしれないストラクチャですが、また機会があったら試していこうと思います。

 

ここ最近時間なくて、これだけの文章書くのに1週間以上かかってしまった・・・

では

今回はこのへんで。