みつまめ杏仁

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

HorizontalBoxの中の表示間隔を調整する

 今回応募したぷちコン作品では、プレイヤーを操作して、浮いているタイルを踏んだ数をカウントしてスコアに加算しています。リザルト画面で表示する際に、ただ数字を書くだけだと面白くないし、「いっぱい踏んだなぁ」「あまり踏めてないなぁ」という実感を噛みしめるためには、ビジュアルで示すのが効果的です。このとき踏む数が想定よりも多かった場合にスキマを詰める処理を実装しました。今回の記事は事例紹介的な感じで書いていきます。

f:id:hiyokosabrey:20180922163532j:plain

10個までは一定の間隔で並べて↑

10個以上になると数に応じて詰めます↓

f:id:hiyokosabrey:20180922163603j:plain

 細かい仕様ですが、0個の時は半透明にしてます。

 ちなみにこの文字の種類による点数差は「屈辱点」てやつで、昔のアーケードゲームでよく見かけた仕様を取り入れてみました。点数獲得の単位が100点刻みだと、普通にプレイすると10の位まで0が並びます。ところがランキング画面(今だとLearderboardsっていう方が通るかな)をよく見ると、1の位に数字が入っていたりします。これは「コンティニューしてる・・・金の力でクリアしやがった」、百以下が 00だと、「お!ノーコンクリア!すげぇ!」となるやつです。コンティニューすると1点もらえる!って素直に喜んじゃいけないのです。

 実はランキング画面も作るつもりだったのですが、ステージのタイルがランダムだとスコアを競う気がなくなるのでやめました。高得点のルートが決まるのも面白くないのでランダムは残すことにした結果、ただの運ゲーになってますw

 

 ちょっと脱線してしまいましたが、Widgetの中身について書いていきます。

キャンバスにはキャラを並べる HorizontalBox と スコア用の TextBlock を並べています。

f:id:hiyokosabrey:20180922181356p:plain

テクスチャは 64x64が4枚。

f:id:hiyokosabrey:20180922212735p:plain

 

これらを、配列に収納してしまいます。

f:id:hiyokosabrey:20180922182442p:plain

 配列に入れておくと、Index番号で扱えるようになるので、ある程度機械的に処理できて便利です。後から要素を追加しても同じように処理できます。また、アナログ的に並んでいるものでも順序を決めて管理できるのも魅力です。

 

 上の図では、Add to Viewport するたびに走るので、Do Once ノードを入れています。リザルト画面が終わったら、Remove from Parent していますが、描画されなくてもメモリには残すようにしているためです。

 この配列たちは一度作ったら、中身が変化せず、繰り返し使用するタイプなので破棄する必要がないのも理由のひとつです。

 

配列の準備ができたので、次はスコアをセットしていく部分です。

別の関数ですでに「ぷ」「ぶ」「ち」「さ」のそれぞれの個数を受け取っています。

それを↓この配列に保持してあります。

f:id:hiyokosabrey:20180922190748p:plain

この配列の中身を ForEachLoop ノードで取り出しながら処理していきます。

f:id:hiyokosabrey:20180922202631p:plain

真ん中付近にいる Pure型の関数 が表示間隔を計算する関数です。

f:id:hiyokosabrey:20180922194153p:plain

並べる文字のテクスチャサイズは 64x64です。 それが10個で640という幅が、表示限界幅とします。

f:id:hiyokosabrey:20180922195349p:plain

まず 引数(Inputs)で受け取った個数で、表示限界幅 640 を割ります。

640 ÷ 個数 で1個あたりの幅が計算できます。そこから 64 を引いた値が、基本の表示間隔 = 64 に対しての補正値となります。

f:id:hiyokosabrey:20180922205801p:plain

 

なぜこんな補正値が必要かというと・・・

例えば、 11個だった場合。

640 ÷ 11 で、58.1818181818・・・ となるので、1個が 58.181818・・・の間隔で並べばいいのです。

ところが、HorizontalBox は追加した 子パーツ の幅をそのまま維持して並べようとします。58.18181818・・・ずつ、といっても聞いてくれません。そこで、SetPadding ノードを使います。

f:id:hiyokosabrey:20180922210214p:plain

 

ここに渡す値を用意するために、もう少し計算が必要です。

 58.1818181818・・・からさらに 64を引くと、

-5.81818181818・・・・ となります。(符号はマイナスになりましたが、小数点が一つ動いただけに見えて面白い結果ですね。)

これで補正値が計算できました。

 

この補正値を HorizontalBox にテクスチャ文字を追加する際にPaddingの値として渡せばいいのです。

その仕事をするマクロがあります。

先の ForEachLoop で処理していたところの、真ん中付近、少し上と右に計2つあります。

f:id:hiyokosabrey:20180922202631p:plain

このマクロの中身はこんなかんじ。

f:id:hiyokosabrey:20180922211025p:plain

HorizontalBox に追加した 子パーツ に対して(正確にはAdd Child ノードの戻り値)、HorizontalBoxSlot にキャスト(型変換)すると、SetPadding ノードがつながります。その In Padding Right に補正値を入れてやると、次に追加された子パーツ がその補正された場所に追加される仕組みです。

ついでに個数が ゼロ だった時の処理も入っています。

 

実際に 8、9、10、11 個の場合の表示はこうなります。

f:id:hiyokosabrey:20180922202052p:plain

 

 状況に合わせて動的に子要素を追加する場合、エディタで事前に予測して調整できればいいのですが、臨機応変な対応が必要となるとブループリントでどうにかすることになります。SetPaddingノードを使うと表示間隔を自在に調整できるので、今回の仕様が実装できました。VerticalBoxでも同様のことができます。

 

ではでは

今回はここまで

ステキな表示間隔ライフを!