みつまめ杏仁

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

[3D]頂点移動でタブウィンドウ的な何かをつくる

 先日4/21のアンリアルフェスに参加してきました。あっという間の8時間で、アンリアルエンジンに関わってる人たちのお話をもっともっと聞いていたい、そんなイベントでした。残念ながら懇親会のチケットは速攻でSOLD OUT。横浜のフェスも行きたいけど遠いな~。

 

 で、今回は3Dメッシュでウィンドウっぽいものを作ってみます。

たまにはポリゴン使ってUI作ってみようかな~などと、思ってみたりしちゃったのでやってみました。まず用意するのはテクスチャとポリゴンメッシュ。メッシュはBlenderを使用しました。

 

まずテクスチャ。

f:id:hiyokosabrey:20180427001732p:plain

サイズは 256x128 今回アルファチャンネル無しのグレースケールテクスチャです。

VRAMの使用量を抑えて非圧縮にできるのでオススメです。

これに、UV範囲が分かるように色付けしてBlenderに持っていきます。

f:id:hiyokosabrey:20180427002033p:plain

 

平面を扱うので、Blenderの場合、作業する際にテンキーの[7]、[5]を押して、トップビューの平行投影にすると、 ペラポリゴンがきちんと平面で編集できます。出来上がりは↓のようになります。

f:id:hiyokosabrey:20180427002718p:plain

一応手順を簡単にメモっておきますね。

Planeメッシュを作成して、ざっくりと上図のように分割します。「ループカットとスライド」を使ってテキトーに割っていきます。

f:id:hiyokosabrey:20180427003942p:plain

このオブジェクトにマテリアルとテクスチャを追加します。そして「編集モード」に切り替えて「UV展開」したら、UVの頂点をテクスチャの色分けに合わせて移動させます。このときUVの頂点は「ピクセルに吸着」にチェックを付けておきます。

f:id:hiyokosabrey:20180427003109p:plain

UVの編集が終わったら、メッシュの頂点を整えます。ざっくりとピクセル基準でOK。モデルのサイズは後からスケールで調整できます。

色分けのピクセルに合わせるように頂点座標を編集しますが、「単位」の設定を確認します。

f:id:hiyokosabrey:20180427224405p:plain

プロジェクトによって、またカメラとの合わせ方によって変わるので、あくまでも参考程度にお願いします。

この設定の場合、1ピクセルを1mとして作っていきます。

f:id:hiyokosabrey:20180427224923p:plain

 ここで、欲しいウィンドウの横幅になるよう左右を引き延ばしておきます。

 

モデルができたら、FBX形式 で エクスポートします。

f:id:hiyokosabrey:20180427225354p:plain

 エクスポート設定は以下。

f:id:hiyokosabrey:20180428223617p:plain

ちょっと小さくて分かりにくいですが、上 は 『 -Yが上 』を選びます。

この設定はBlenderを終了しても覚えておいてくれないので、+ ボタンをクリックしてプリセットにしておくのをオススメします。

 

名前をつけて書き出したら、UE4のコンテンツブラウザにドラッグ&ドロップします。

このときちょっとだけ待ってあげてください。おそらく中身を解析してます。

f:id:hiyokosabrey:20180428104734g:plain

 

インポート設定のウィンドウがポップアップするので、確認しながら調整します。

基本的にデフォルト設定のままで大丈夫ですが、無用なデータが作られるのは避けたいので、チェックした方がいい個所を記しておきます。

f:id:hiyokosabrey:20180428111451p:plain

FBXに関して詳しいことは公式サイトをぜひ

Unreal Engine | FBX コンテンツ パイプライン

 

これで無事インポートできたら、テクスチャもインポートします。

インポートしたテクスチャからマテリアルを作成(Create Material)します。

テクスチャはグレースケールで作っています。

あと、もう一枚テクスチャを追加します。

UV座標をすこしカバーするように、赤と青で塗りつぶします。

f:id:hiyokosabrey:20180428113906p:plain

※分かりやすいようにオレンジのラインを重ねています。

赤は(255,0,0)青は(0,0,255)にします。

255 を使わないと計算のときに 1.0 にならないのでご注意を。

この単純な色ベタのテクスチャを 32bpp のフルサイズ で作るのはテクスチャメモリがもったいないので、解像度を下げます。この時、ニアレストネイバー を選択するとピクセルがボケません。できるだけ 1/2、1/4単位で縮小します。赤と青のピクセルも基本的に奇数は使わない方が無難です。これはテクスチャを作る場合は偶数を基本にした方がいいです。あくまでも面積的な話です。で実際に使ったのがこれ。

f:id:hiyokosabrey:20180428114908p:plain

64x32です。

これをマテリアルに追加するのですが、テクスチャのフィルタ設定を変更します。

2枚のテクスチャ設定を並べてみます。

f:id:hiyokosabrey:20180428115949p:plain

これをマテリアルで組んでいきます。

 

 マテリアルは、光源計算しないのと、半透明なので、

f:id:hiyokosabrey:20180428214009p:plain

全体図はこんな感じ。

f:id:hiyokosabrey:20180430144459p:plain

キーになるのは LocalPosition ノード。

f:id:hiyokosabrey:20180430144815p:plain

ここから頂点座標を取り出したものに、マスクテクスチャを使って値を作り、X軸とZ軸にそれぞれ足し算してやります。

緑のScalarParameterノードは、ブループリントからいじるためです。

f:id:hiyokosabrey:20180430144907p:plain

頂点をいじった状態を本来のオブジェクト位置に引き戻したいので 絶対ワールド位置 ノードを使います。この Absolute World Positionノード、 Absolute で検索しても出てこなくて、普通に World Position で並んでて取り出すとこのカタチになる。

f:id:hiyokosabrey:20180430145504p:plain

ネットの参考画像と合わなくてくじけそうになった。

 

 

マテリアルができたら、スタティックメッシュのアセットを開いてセットします。

f:id:hiyokosabrey:20180428214617j:plain

 

Actor型のブループリントを用意します。

f:id:hiyokosabrey:20180428214933p:plain

さっそく編集していきます。

まず、左上の緑のボタンから Static Mesh を追加します。

f:id:hiyokosabrey:20180428215252p:plain

追加したStaticMeshコンポーネントは、名前を変更できます。

追加できたら、右のDetailsタブから、作ったスタティックメッシュをセットします。

f:id:hiyokosabrey:20180428224323j:plain

 

続いて、EventGraphを編集します。

その前にConstruction Scriptで透明度のセットをしておきます。

f:id:hiyokosabrey:20180430150549p:plain

出現時は透明なんですが、最初の配置調整が大変なので、ここで強制的に 1.0 にします。マテリアルにセットしたパラメータ ”Opacity” に値を渡します。最後に準備ができたら 0.0 に戻します。

 

次に

EventGraphにカスタムノードを置いてつないでいきます。

f:id:hiyokosabrey:20180430151329p:plain

タイムラインノードの中身はこんな感じです。Float型が2つ。

f:id:hiyokosabrey:20180430151654p:plain

ウィンドウの高さ = Height は、固定の値にするのではなく、0.0 ~ 1.0 のアニメーションにします。こうしておくと、いろんな値を掛け算するだけで自由なサイズのアニメーションが作れます。

 

出現アニメーションができたのでテストしてみます。

スポーンされた想定で、EventBeginPlayノードから、上のカスタムイベントを呼び出すことにします。

f:id:hiyokosabrey:20180430152546p:plain

コンパイルして保存したら、シーンに適当に配置します。

再生しすると、

f:id:hiyokosabrey:20180430153630g:plain

いい感じになりました。

UMGを使わずに、Scal9Grid ぽいことができました。

なんかVR空間のUIで使えそうな予感。いかがでしょうか。

別のアングルから見ると3D空間に浮いているのが分かります。

f:id:hiyokosabrey:20180430154332j:plain

 

テクスチャで頂点にマスクをすることで、動かしたい頂点を選び分けることができました。

 

今回は以上です。UMG推しではありますが、3D の UI制作についても記事を書いていけたらと思ってます。

 

ではでは

ステキな3Dウィンドウライフを!

 

 

 

 

 

 

 

 

 

 

 

 

UMGのテキストブロックで遊ぶ

とあるRPGの曲を作業用に聞きながらYoutubeの動画をチラ見してたら、テキストの表現方法がたくさんあったことに感動したのを思い出しました。で、ふと試してみようと思たったのが今回のネタです。過去記事で似たようなことをやってるのでその応用ってことになるのかな。

 

limesode.hatenablog.com

基本的に同じような作りです。ちょっと味付けが違う程度なので、細かい解説は省きます。

今回やろうとしている機能は2つ。

  • 1文字ずつタイプライター風に表示
  • 文字を震わせる

 

1文字ずつ出すだけだったら、テキストブロックひとつあればいいのですが、バラバラにする必要があって、さらに改行もするのでちょっと面倒なプロセスが入ります。

 

大雑把ですが、

  1. 改行付きの文字列(String型)を受け取る。
  2. 改行文字(エンジン内ではShift+Enter)で区切って文字列の配列を生成。
  3. その配列を行毎のHorizontalBoxに格納。
  4. 文字をぶるぶるさせる
  5. 一文字ずつAlphaを1.0にする

というフローでやってみます。

 

まず吹き出しテクスチャ。前回の記事に倣ってグレースケールで作りました。

f:id:hiyokosabrey:20180418231516p:plain

インポート設定で、フィルターを ニアレストにしておきます。

f:id:hiyokosabrey:20180418231828p:plain

拡大縮小の際のフィルタリングでドットをそのままにする設定です。

 

UMGのキャンバスに表示のON/OFFをラクするためにキャンバスパネルを置いて、中に

フキダシ画像と、文字を流し込むためのHorizontalBoxを並べます。

f:id:hiyokosabrey:20180418232541p:plain

 4行分に対応。

一応 HorizontalBoxは Size to Content のチェックを入れてあります。

f:id:hiyokosabrey:20180418232834p:plain

このHorizontalBoxを4つに分けたことで、文字列を「行」ごとに分割することになった

 最大の理由です。ローカライズを考えるならもうちょっと対策した方がいい気もしますが、あとから改行位置を調整するのを前提とした作りにしています。

Hiearchyはこんな感じ。

f:id:hiyokosabrey:20180419223029p:plain

 

Widgetブループリントを編集していきます。

HorizontalBoxはすでにキャンバスに置いてあるので、扱いやすくするために、Event Pre Constrct で配列化しておきます。

f:id:hiyokosabrey:20180419223215p:plain

 ブーリアン型の変数は、いきなりブルブルしないようにするためのフラグです。今はまだ false 。

 

まず関数を3つ。

 

ひとつ目

文字列を分解して、新しく1文字づつのテキストブロックを生成する関数。

f:id:hiyokosabrey:20180419224615p:plain

 

2つ目

指定した文字列(Delimiter)が文中に見つかると、それを配列にバラして格納します。

f:id:hiyokosabrey:20180419231005p:plain

 Parse Into Array はとても便利なノードです。

f:id:hiyokosabrey:20180419230145p:plain

 デリミタで使用した文字は消滅します。何が便利かって個別の値(この場合は文字列)を1文で扱うことができるという点です。本当は改行文字のようなOSやプラットフォーム依存の文字は避けるのが基本ですが、今回はお遊びということで。

 

3つ目

外部から文字列を受け取って表示する関数。上の2つの関数を組み込みます。

f:id:hiyokosabrey:20180419231325p:plain

 For Each Loop の処理が終わったら、表示開始になりますが、ひとまずイベントグラフに戻ります。

 

Event Tick でぶるぶるする処理を用意します。

Event Tick は、この WidgetViewportにAddされた瞬間から動き出します。

f:id:hiyokosabrey:20180419231611p:plain

 ランダムに ポジションを動かしますが、今回は微妙な値が連続しないようにInt型の乱数にfloat型の値を掛けています。

 

ここでフラグを見ています。文字の数が確定してないうちから処理するのは無駄なので、フラグが True になるまで処理しないようにブロックしています。

 

タイプライター風の動きをするのが、このカスタムイベント。

f:id:hiyokosabrey:20180419232511p:plain

ポイントなのがこの部分↓

f:id:hiyokosabrey:20180419232958p:plain

過去記事 『キーリピート機能をつくってみる』でも書いています。

 

だいたい用意ができたので、仕上げに3つ目の関数を編集します。

For Each Loop ノードの、Complete ピンの続きです。

f:id:hiyokosabrey:20180419233347p:plain

まず表示を Visible にして、フラグを True にしたら、タイマーノードです。

フキダシが表示されたら、人は目で追います。そのタイミングで文字を表示するのは視線誘導の効果が台無しなので、少し待ってあげるためのものです。Function Name のところに、タイピング処理用のカスタムイベントの名前をセットします。

 

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

 

 

確認

あとは適当にレベルブループリントから呼び出して確認します。

f:id:hiyokosabrey:20180419234030p:plain

 

こうなります。

f:id:hiyokosabrey:20180419234615g:plain

そう、とあるRPGというのは、UNDERTALE です。

その登場キャラの一人、フラウィのセリフです。

もう一つキャプリました。

f:id:hiyokosabrey:20180419235219g:plain

多分、まったく効果はない気がしますが一応ネタバレ対策で英語版にしてみました。

アイツの笑い声がよみがえります。

 

だいぶ遅れて遊んだのですが、ほんといいゲームですね。

読み物としてテキスト表現にこれほど凝った見せ方をしたゲームいままであっただろうか、というところも感動しました。UI表示を考えるとき、システム的に汎用性を意識するものですが、そんなのお構いなし、って感じです。まだ遊んだことのない方、ぜひ一度ご賞味ください。クレジット画面も凄まじい作りこみです。

 

今回も目コピーネタでしたが、楽しいのでまたやろうと思います。

ではでは

ステキなテキストブロック ライフを!

 

 

 

 

グレースケールテクスチャ 続き

Photoshopでいい感じのグレースケールテクスチャが作れたので、さっそくエンジンで検証します。もちろんUE4です。テクスチャだけの話だったらUnityでも使える内容ですが、ここからはアンリアルエンジンです。

テクスチャは2種類用意しました。

RGB24bpp の変換前のものと、 グレースケールに変換済みの2つです。どちらも同じ見た目ですが、ファイルサイズが違います。

f:id:hiyokosabrey:20180408134530p:plain

このテクスチャをインポートします。

 

どちらも同じ設定にします。このタイミングでGrayscaleを選択します。

f:id:hiyokosabrey:20180409215154p:plain

Compression SettingsGrayscaleに変えて、sRGB のチェックを外すと、晴れてリニアなグレースケールテクスチャとしてアセット化されます。

インポート後のDetailsタブを比べてみると・・・

f:id:hiyokosabrey:20180409215354p:plain

どちらも Resource Size8KbっておいおいPhotoshopでグレースケールにする意味なかったじゃん。なんか悔しいので、Contentフォルダの .uasset も一応チェック。

24bppの方は 3907Bytes 、 グレースケールの方は、 3745Bytes。うん、

ほんのちょっぴり差があった。ファイル名は2文字しか違わないので、何かしらおまけがくっついてるみたい。エンジンに取り込まれた後なら違いなんてなくて当たり前か。

 

さて次の検証。マテリアルの LinearGradientノードと勝負です。

f:id:hiyokosabrey:20180409220538p:plain

頑張って作ったテクスチャに何らかの変換がかかったりしてると悲しいので、計算で出力されるリニアなグラデーションと比べることで確認します。

「リニアな」というのは、0.0~1.0(0~255)までを何の補正もせず素直に使用している状態です。上の LinearGradientノードは値が偏らず均質なグラデーションになるうえ、テクスチャのような解像度というシガラミが無いのでゲージを作ったり背景などに大活躍です。

 

2つのテクスチャと、LinearGradientノードの合わせて3つで、マテリアルを作って、UMGで表示させてみました。

f:id:hiyokosabrey:20180409224435p:plain

なんだか明るいですが・・・3つとも同じように見えます。念のために適当な場所をサンプルとして差がないか確認します。

f:id:hiyokosabrey:20180409225839p:plain

残念ながら 0(黒)に近い部分で差異が出ています。画面キャプチャなので、エンジンの出力時に何らかの補正が入っているかもしれません。・・・というか全部にガンマ補正が入っているようです。中央が128じゃない時点で気づいてもおかしくないのですが、LinearGradientとの勝負でそこをスルーしてました。

sRGB空間な見た目なので、ノードで調整してみます。

f:id:hiyokosabrey:20180410232658p:plain

 

結果はずいぶんリニアっぽくなりました。

f:id:hiyokosabrey:20180410232726p:plain

ということで、何もせずそのままリニアなテクスチャを持ってきても、画面に表示されれば、sRGBになっているということが判明しました。

 

 今回リニアワークフローの検証をしたかったわけではないので、これ以上の深追いはやめておきます。そう、テクスチャの節約です。高解像度時代への橋頭保としてグレースケールテクスチャの扱い方を検証していたのでした。

 ちょっとサンプルを作ってみました。

用意したテクスチャはこれ。

f:id:hiyokosabrey:20180410235256p:plain

サイズは 1024x512pxです。圧がすごい・・・

次に用意したのは、

f:id:hiyokosabrey:20180410235408p:plain

サイズは 8x256px。

これをインポートして、マテリアルを作成します。

シンプルにマスクテクスチャとしての利用です。

f:id:hiyokosabrey:20180410235748p:plain

表示してみます。

ドーーーー~ン!という重低音が聞こえてきそうです。CMみたい。

f:id:hiyokosabrey:20180410235942p:plain

サイズ比較用に、解像度は同じ1024x512で RGBA8888 の 32bppのテクスチャを作ってみました。さっそく比較します。まずはG8から。

f:id:hiyokosabrey:20180411001212p:plain

f:id:hiyokosabrey:20180411001301p:plain

そしてRGBA32bpp

f:id:hiyokosabrey:20180411001313p:plain

f:id:hiyokosabrey:20180411001323p:plain

実に4倍の容量になります。圧縮すれば小さくなりますが、こういった文字やUI表示は劣化したテクスチャは悪目立ちします。凝った見た目は 32bppじゃないと無理ですが、クリアなエッジを保ちつつ、容量節約できた分バリエーションを持たせることができるグレースケール、どちらを採用するかはその都度相談しながら決めればいいかと思います。

 

大事なこと書くの忘れてました。UMGでは、直接グレースケールテクスチャを貼ることはできません。できなくはないですが見た目に赤くなります。しかも透過しない。

f:id:hiyokosabrey:20180411002631p:plain

これはチャンネルが 一つしかないためで、RGBAの4チャンネルのうち R

チャンネルのみに、グレースケールの値が適用されるからです。

 

普通にUMGで着色したい場合はこのようなマテリアルを用意します。

f:id:hiyokosabrey:20180411003527p:plain

これをImageパーツに適用すれば Color And Opacity で色が付けやすくなります。

f:id:hiyokosabrey:20180411003550p:plain

ちょっと手数が増えますが、テクスチャの容量が稼げるのが素晴らしいです。

マテリアルをちょこっと改造してインスタンス化できるようにしてみました。

f:id:hiyokosabrey:20180412000057p:plain

テクスチャサンプルパラメータノードに差し替えます。このノードに名前を付けて、テクスチャフォーマットをLinearGrayscaleに変えます。そして安全な状態にするために、

16x16程度の ■ ダミーテクスチャを作ってセットしておきます。

f:id:hiyokosabrey:20180412000539p:plain

このマテリアルからマテリアルインスタンスを作成します。マテリアルアイコンの上で右クリックして一番上にあるのを選択すると作ることができます。

f:id:hiyokosabrey:20180412000803p:plain

マテリアルインスタンスの中でテクスチャをセットする項目があるのでそこに用意したグレースケールテクスチャを登録します。

f:id:hiyokosabrey:20180412000901p:plain

あとはUMGで Image にセットするだけ。

 

基本はマスク的な使い方が一番向いてるのですが、ちょっと変わった使い方をしてみます。

 

Photoshopで雲模様フィルタを使うと簡単にシームレスなテクスチャが作れます。

f:id:hiyokosabrey:20180412053704p:plain

これを、Pannerでスクロールさせ、TexCoordに足してやると、

f:id:hiyokosabrey:20180412054420p:plain

 ゆらゆらと陽炎のように歪みます。水の中の表現としてもありです。

f:id:hiyokosabrey:20180412060452p:plain

 おなじ雲模様テクスチャに対してValueStepを使って掛けてみると、

f:id:hiyokosabrey:20180412055308p:plain

 ブループリントからScalaParameterノード ”Value” の値を 0.0~1.0 に変化させます。

f:id:hiyokosabrey:20180412060041p:plain

f:id:hiyokosabrey:20180412060050p:plain

f:id:hiyokosabrey:20180412060059p:plain

出現や消滅の演出に使えそうです。

 

といった感じで、まだまだ探せばネタはありそうですが、今回この辺にしておきます。

グレースケールテクスチャを使うと、テクスチャ容量を稼いでリッチな見た目を作るのができて楽しいです。

 

ではでは

豊かなグレースケールライフを!

 

グレースケールテクスチャ

ふと気になって、グレースケールについて調べることにしました。

UI表示のためのテクスチャは、アルファチャンネルを使った半透明で「抜き」を扱うことがほとんどなので、Photoshopで作ることが多いと思います。

 

で、ちょっと解像度の話

 最近のモニタ解像度は1080pがまだ強い印象ですが、PS4Proのせいで4K対応も考えなくてはなりません。解像度が低いうちは1文字が 8x8(実際は7x7) で下のような大きさでしたが、(っていつの話やねん!)

f:id:hiyokosabrey:20180408002322p:plain

↑この 320x240(4:3)をTV画面サイズとしたときに、単純に 1440x1080(4:3)に拡大して、だいたい同じようなバランスの大きさにしてみたら、1文字につき 約34pxは必要になります。

下図は、いったん1440x1080を横に拡張して 1920x1080(16:9)にしたものを上の画像に合わせて縮小したものです。

f:id:hiyokosabrey:20180408213303p:plain

 

拡大前と後を比較用に近づけて並べてみました。

f:id:hiyokosabrey:20180408004458p:plain

↑の画像のように拡大してボケボケだとかっこ悪いので、鮮明なテクスチャを用意したいものです。そのためにはテクスチャ解像度を上げることになるのですが、当然グラフィック用のメモリを圧迫します。UIのために容量を存分に分け与えてくれるなんてことは滅多に無いので、テクスチャの節約について考えなくてはなりません。解像度を確保するのに結構やりくりが必要です。

 そこで登場するのがグレースケールテクスチャ。単純なマテリアルだけで着色できるし、最近はシェーダーで加工するのが手軽になったので 結構活躍できます。何よりもファイルサイズが1/4で済むということは、RGBA32bitの絵のサイズと比べて4倍のサイズの大きさのテクスチャが作れるということです。

 

で、Photoshopの話

Photoshopでこのグレースケールテクスチャを作る方法は、大きく2つ。

  • 先にグレースケールで作業を開始する
  • 後からグレースケールに変換する

 実際に作業してみると問題が見えてきました。

気にしなければどうということはないですが、品質的に解像度の大きなモニタだと粗さが際立ちます。

先にグレースケールのドキュメントとして作業を始める場合の問題点は、ブラシカラーが K値(CMYKのK)で扱うので0~255階調ではなく、0~100の”%” というところ。

f:id:hiyokosabrey:20180408132636p:plain

小数点が使えないので、階調の少ない環境で作業することになります。あくまでもこれはブラシや塗りつぶしで細かく選択できないだけで、ぼかしフィルタやトーンカーブではしっかりと256階調が使われます。ゲージとかのリニアなテクスチャを作るにはちょっと工夫が必要です。あと個人的に気になるのは、作業効率という点でカラーが使えないので、UVのアタリ取りとして色分けできないところです。

 

後からグレースケールにした場合は要注意です。

Photoshopの初期設定だと、以下のようになります。

まず RGBで 256階調のリニアグレー

f:id:hiyokosabrey:20180408134530p:plain

これをグレースケールにモードチェンジするとこうなります。

f:id:hiyokosabrey:20180408134600p:plain

ピクセルを2倍に拡大していますが、ちょっと分かりにくいですね。

さらに部分拡大(1600%)にすると見えてきます。

f:id:hiyokosabrey:20180408134939p:plain

モニタによっては見えにくいですが、ディザ処理がされています。これはテクスチャの扱いによっては(雲とか煙みたいな繊細な半透明を扱うときとか)ノイズになります。

これを回避するには、カラー設定を変更します。

 

編集カラー設定

f:id:hiyokosabrey:20180408135432p:plain

変換オプションの「ディザの使用...」のチェックを外します。

チェックを外してからグレースケールにすると、ディザはなくなりましたが、

f:id:hiyokosabrey:20180408140037p:plain

キレイに並んでいたはずの段階がなんか怪しいことになります。

拡大してみるとなんだか不規則に並んでいます。よく調べてみるといくつもの段階が省略されているのが分かります。

f:id:hiyokosabrey:20180408140237p:plain

なぜこんなややこしいことをしているのか分かりませんが、Photoshopなりの愛か何かなんでしょう。いろいろ補正が入ってしまうのは仕方ないですが、なんだかやるせない感じに包まれつつカラー設定をいじっていたら、いい感じにできるやつを見つけました。

編集カラー設定

作業用スペースにある「グレー」を  sGray に変更します。

f:id:hiyokosabrey:20180408141818p:plain

この設定を変えてから、グレースケールにモードチェンジすると、損失のない素直なグレースケールに変換できました。

これなら、256階調のグレーでペイントできて、作業途中でカラーも扱えるのでいい感じです。

 

あとはこれを書き出せばテクスチャとしてエンジンで利用できます。

 テクスチャフォーマットはTarga形式。拡張子TGAで書き出します。このフォーマットは可逆圧縮で劣化しないし、結構いくつものビットフォーマットに対応してるので大変使い勝手がいいです。PhotoshopでTarga書き出しを行うと、普通だとポップアップが出て面倒です。

f:id:hiyokosabrey:20180408213911p:plain

しかもこのポップアップ直前の書き出し時の選択肢を覚えているので、切り替えが必要な時に一瞬戸惑うので嫌いです。アルファチャンネルの有無で見てくれればいいのに・・・

このポップアップがグレースケールで書き出す際は出ないので、ちょっとだけ幸せな気持ちになります。

 

書き出したファイルサイズを見てみるとちゃんと差があることが分かります。

 

 例えばこんな画像。サイズは 256x256px

f:id:hiyokosabrey:20180408214848p:plain

これを↓のようなチャンネル構成にしておいて

f:id:hiyokosabrey:20180408220155p:plain

それぞれのBPP(bits/pixel =1ピクセル当たりのビット数)で書き出してみました。

グレースケールを1とすると、だいたい3倍、4倍になってるのが分かります。

 

で、整理すると

グレースケールでのペイントや塗りつぶしは100段階の中からしか選べない。(256階調を使えないという意味ではない)

RGBモードのドキュメントで作業してからグレースケールに変換した際に、Photoshopの初期設定だと問題があったので、設定を変えないと、きちんとリニアなグレーにならない。

 

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

 解決策が見つかったので、次回はエンジンに持っていって検証します。

ではでは

ステキなグレースケールライフを!

 

 

で、先日の話

ようやく勇気を出して、Twitterアカウントを作りました。

このブログにあるコメントしづらかったり、何かネタを提供してくださる場合などお気軽にご利用くださいませませ。お手柔らかに宜しくお願いします。

 

 

ボスゲージを作ってみる

RPGとかアクションゲームのボス戦なんかで、ボスキャラの体力がものすご~くたくさんあるのを表現したゲージがありますが、そのひとつ作ってみました。

f:id:hiyokosabrey:20180401224309j:plain

参考にしたのは、大人気モバイルゲームタイトルのFGOです。

普通は1本のゲージが何本もあるかのように見せるタイプが多いです。

例えば1本分がHP1500だとしてその4倍のHP6000をボスが持つ場合、単純に4本分削ることになります。その場合ゲージの色分けで表現すれば十分伝わると思うのですが、

f:id:hiyokosabrey:20180401231231p:plain

FGOは少し違いました。

長さは同じでも1本分にあたるHPの量が違うのです。それはゲージに添えられている数字が説明しています。また、ゲージの下にある◆アイコンがゲージのカラーと連動しています。この◆はいったい何を説明しているのか最初分かりませんでした。

単にゲージの本数を表しているだけでこんなアイコン置くかな・・・、と思いながら攻略サイトを眺めていると、どうやら、ボスキャラたちはゲージのカラー(段階)によって攻撃パターンを変えてくる仕様になっている様子。そういえばHP量を表す数字も、毎回カラーごとに一旦 0 になってから新しく仕切り直しています。ラスボスとかでよく見かけるやつです。HPがある程度減ったら形態が変わってHPが再充填されたりする。その段階を◆のアイコンで分かりやすくしてるようです。

いろいろ納得したところで、UE4で作ってみたのを紹介します。

 

色分けはマテリアルで

マテリアルでゲージを作るときは、テクスチャを使ったUVスクロールか、LinearGradientとValueStepコンビの2パターンを良く使います。今回は後者で。

f:id:hiyokosabrey:20180402003418p:plain

左の Valueと書かれた Scalar Parameter Valueノードの初期値は 1.0 にしておきます。

 

質感を出すためにテクスチャを追加します

f:id:hiyokosabrey:20180402003039p:plain 4x40 px のGrayScale

Addノードを使って間に割り込ませます。

f:id:hiyokosabrey:20180402003833p:plain

ブループリントからいじるためのパラメータ用のノードが3つあります。

長さを変化させるのが ScalarParameter です。

f:id:hiyokosabrey:20180402004237p:plain

この変数を 0.0 ~ 1.0 に変化させることになります。

f:id:hiyokosabrey:20180402005017p:plain

今回2本分のゲージをマテリアルで切り替えるようにした理由は、登場や退場演出などで、アルファフェードしたときに重なりを見せなくするためです。

マテリアルは完成。これをUMGに仕込んでいきます。

 

◆用のWdget

ゲージ下のアイコンを別Widgetで作ろうか悩んでみたけど、結局ラクするために用意することにします。

まずUMGのキャンバスに3つのImageパーツを重ねます。

f:id:hiyokosabrey:20180402215453p:plain

 

f:id:hiyokosabrey:20180402215933p:plain

真ん中のパーツには作っておいたマテリアルをセットします。このパーツにブループリントから色のパラメータを渡して着色します。

 

次に消滅アニメーションを用意します。

f:id:hiyokosabrey:20180402220450g:plain

ヒビが入って飛び散る動きをさせたかったのですが説明が長くなるので別に機会にします。ひとまず白くなって消えるだけですが、これはエフェクト用のパーツをアルファ値のフェードで登場させ最後のフレームで下敷きを残して消しています。

VANISHというアニメーション名にしておきます。

 

次にブループリントを編集します。

カラーを受け取る関数を用意します。

f:id:hiyokosabrey:20180402224457p:plain青いピン(引数:DetailsタブのInputsの項目で追加)はLinearColor型です。

f:id:hiyokosabrey:20180402224839p:plain

関数が用意できたら、EventGraphに戻って、カスタムイベントを一つ用意します。

これは消滅時のアニメーションを再生するためのものです。

f:id:hiyokosabrey:20180402225038p:plain

以上で◆アイコン用のWidgetは完成です。

 

 

HPゲージ本体

ゲージ本体のWidgetを作っていきます。

キャンバスはこんな感じ。

f:id:hiyokosabrey:20180402225837p:plain

ゲージ本体のパーツは、マテリアルをセットしておきます。

f:id:hiyokosabrey:20180402230251p:plain

マテリアルでゲージを変化させるので、このゲージの長さは適当でOK。

 

左下の Horizontal Box は Panelカテゴリのパーツで、ブループリントから子供Widgetを追加すると自動で水平方向に並べてくれる便利なやつです。サイズが小さいのは中身に合わせて可変する設定 Size to Content が 有効(True) になっているからです。この時点では中身はカラです。

f:id:hiyokosabrey:20180402230657p:plain

下敷き以外のパーツは、 必ず Is Variable にチェックを付けておきます。

f:id:hiyokosabrey:20180402231201p:plain

これでブループリントからいじることができます。

UMGは以上です。

 

ではブループリントを編集していきます。

まずは Event Pre Construction イベントから。

f:id:hiyokosabrey:20180402231424p:plain

このイベントはコンパイルした時点で処理される特殊なイベントです。

変数の初期値をセットしたりするのに向いています。

 HPの段階は配列変数で管理したいので、段階ごとのカラーをLinearColor型の配列変数で用意します。マテリアルを頻繁にいじることになるので、ここで Dynamic Mterial Instance 作って変数化しておきます。Get Dynamic MaterialノードのReturn Value ピンの上で右クリックして Promote to Variable を選択するとラクちんです。

 普段 マテリアルは Static(静的)なものとして扱われます。ブループリントからいじりたい場合はDynamic(動的)なものとして扱います。この辺はお約束として覚えておけばいいと思います。

 

つぎに関数を5つほど用意します。

 

まず一つ目 簡単なとこから。

showVital

f:id:hiyokosabrey:20180402232623p:plain

引数でもらったInt型の値を、UMGのテキストブロックに流し込みます。

 

2つ目

setVitalColors

f:id:hiyokosabrey:20180402232809p:plain

 ゲージのマテリアルにカラーを渡す関数です。

 

ここで、段階ごとのHPを配列で受け取るための変数を用意します。

f:id:hiyokosabrey:20180402233130p:plain

用意できたら3つ目の関数

setVitalValue

f:id:hiyokosabrey:20180402233348p:plain

今現在のHPを、その段階に設定されているHP(配列に格納)で割ると、比率が出ます。それをマテリアルに渡すとゲージが変化します。今回ゲージを右から左に向かって減らしたいので、1.0から引き算しています。

 

ここで、Int型の変数を2つ新しく追加します。名前は Vital と Level にしました。

ボスのHPを保持するのと、段階を保持する変数です。配列にはしません。

 

この時点で 変数リストはこのようになってます。

f:id:hiyokosabrey:20180402234335p:plain

上の方のUMGパーツたちは、Is Variable にチェックをつけるとここに並びます。

一番下の Boss~ はこの後説明します。

 

4つ目

initGauge

f:id:hiyokosabrey:20180402233803p:plain

先に用意した関数を並べます。引数で指定した段階のHPでグラフをセットします。

開始時と段階が進んだ時にこの関数が呼ばれます。

 

5つ目の関数をに行く前にマクロを作ります。

ブログで説明するには長くなるので、マクロにまとめました。

initSubVitalIcon

f:id:hiyokosabrey:20180402235623p:plain

 受け取った配列の数から1ひいた分だけ ◆用Widgetを生成して並べます。後でいじるので、生まれたばかりのWidgetを配列の形で格納(空っぽの配列にAdd)しています。Create Widget ノード の Return Value ピンの上で右クリックして Promote to Variable を選択した後、いったんそのSetノードをグラフから削除します。そしてDetailsタブの方で配列化します。

f:id:hiyokosabrey:20180403000208p:plain

 

いよいよ5つめの関数

setupBossVital

f:id:hiyokosabrey:20180403000636p:plain

この関数が外のブループリントから、ボスのHPを配列で値をもらいます。

 

最後にカスタムイベントを作ります。

このイベントでダメージ分を受け取ってゲージを減らします。

updateVitalValue

f:id:hiyokosabrey:20180403001330p:plain

ダメージの値を受け取って、現在のVitalから引き算します。それを再び変数にセットして、判定を取ります。0以下、ということはマイナスになったかどうかを確認します。

 

いいえ(0以下ではない)だった場合

f:id:hiyokosabrey:20180403001831p:plain

そのままゲージの見た目を更新

 

はい(0以下)だった場合

f:id:hiyokosabrey:20180403002037p:plain

 段階を一つ進めます。こここでも段階がまだあるかどうか判定してから次に進みます。

下段はもう段階がないので、事実上ボスは倒したことになります。

 

以上で完成です。

 

さっそくレベルブループリントからテストしてみましょう。

f:id:hiyokosabrey:20180403002655p:plain

とりあえず段階は4にしてみます。

この状態では、ゲージが減らないので、シミュレーション用のInputイベントを使います。

UE4はキー入力のイベントを扱うノードが充実してるので好きです。

f:id:hiyokosabrey:20180403003013p:plain

 スペースキーを押すたびに、500~5000のランダムな値をゲージWidgetの関数に送り込んでいます。ダメージとして計算してくれるはずです。

 

f:id:hiyokosabrey:20180403004335j:plain

f:id:hiyokosabrey:20180403004347j:plain

無事動いています。

f:id:hiyokosabrey:20180403004414j:plain

ちゃんと下の◆も連動しています。

f:id:hiyokosabrey:20180403004446j:plain

カラーを配列にしているのですが、0番目を透明にしている訳は↑これです。

f:id:hiyokosabrey:20180403004930p:plain

動作がかなりそれっぽくなったと思うのですがいかがでしょうか。

 

今回はFGOの敵HPゲージを目コピしてみましたが、なかなか楽しかったので、また気が向いたら既存のタイトルを再現してみます。

 

ではでは今回はこの辺で

ステキなボスゲージライフを!

 

 

横方向のアイテム選択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ライフを!