ストラクチャを使ってみる
前にEnum(いーなむ)を使ったリストメニューについて書きましたが、最近になってUser Defind Structureが便利なことに気付きました。
ストラクチャはプログラム界では《構造体》とか呼ばれているようで、Enumと同じように、アセットで管理できます。Enumと違って中にいくつでも変数を仕込むことができるので、使い方によっては、とても頼もしい存在になってくれそうです。
作り方は簡単。コンテンツブラウザからいつも通り右クリックして作れます。
で生まれたのが下のアイコン。
コンテンツアイコンには、New User Defined Structure とあります。
「新しくユーザーが定義した構造体」ということになるのでしょうか。
いい感じの名前を付けたら、編集ウィンドウを開いて、変数を追加していきます。
上の例ではText型の配列変数を一つ追加しました。
Saveして閉じたら、このストラクチャを使おうとしているブループリントを開きます。
そこで変数を追加します。
変数を追加したら、型(VaribleType)を変更するのですが、リストの中に自分の作ったストラクチャが追加されているはずなので、それに変更します。
下図はストラクチャの名前と変数名を "ListName" にした場合です。
値を取り出す場合は、Breakノードを使います。
ストラクチャだと配列が扱えるので、値を取り出すのも簡単。ForEachLoopとの連携も便利です。
他にもいろんな型の変数が扱えるので、マテリアルパラメータコレクションみたいな使い方も便利そうです。アセットなので、カラーを初期値として設定しておけば、いろんなブループリントで共有することができるので、カラールールを揃えるのも簡単。一斉に修正や調整ができて便利そうです。
変数として扱えるということは、当然、値をセットすることもできます。
その場合、Makeノードを使います。
アセットの中身が書き換わるわけではないので、普段の変数と同じように扱えばOK。ただ、SetとGet のカタチで直接触れないので、BreakとMakeノードの助けを借ります。
なんとなく便利そうなストラクチャですが、ちょっとだけ気を付けることがあります。
ストラクチャのアセットを編集すると、そのストラクチャを使用しているブループリントすべてが自動的にコンパイルされ、未保存の状態になってしまいます。新たに別のレベルを開くか、エンジンを終了しようとすると、ダイアログが出てきて保存するかどうか訊いてくるので、うっかりDon't Save を選ばないように。
そんなに使いどころは無いかもしれないストラクチャですが、また機会があったら試していこうと思います。
ここ最近時間なくて、これだけの文章書くのに1週間以上かかってしまった・・・
では
今回はこのへんで。
UV座標の計算をマテリアルでやらせると指定がラクチン
以前、マテリアルのパラメータ指定で細かい小数を扱っているのを、改良する記事を書きました。
今回はもう少しだけ発展させます。
テクスチャの一部を切り出して使うには、UとVの2つの値を扱うことになります。このUとV、2つの値を渡すには、Set Scalar Parameter Value を2つ並べるか、
Set Vector Parameter Value の4つあるピンを贅沢に使うか、
処理される時間を考えると、Vectorのように一度に値を渡せた方がいいけど、なんかちょっともったいない気もしてて、もっとスッキリできないかなと考えてたら思いつきました。(またもや前置きが長い)
配列変数はもう使いません。
その代わり少し計算が必要になります。
これも過去の記事で書いたのが参考になります。
この記事でグリッドに並べるための計算方法を説明しました。これをマテリアルに応用してみたのが下の図。
パラメータノードは、スカラー型が1つだけです。見慣れないやつがいるかもですが、値を調整する部分は4か所です。
しかも必要な数値は3つ。簡単に計算できます。
テクスチャのサイズは ヨコ 512 タテ 256 の場合です。アイコン1つ分の大きさは 80x80 なので、UとVそれぞれのサイズは以下のようになります。
80 ÷ 512 = 0.15625
80 ÷ 256 = 0.3125
必要な3つの数値のうち2つが確定しました。3つ目は並んでいる数です。
横方向に6つずつ並んでいます。この並んでいる数を計算に使用することでアイコンのUV座標(場所)を割り出します。このマテリアルさえ完成すれば、ブループリントはプログラマに管理してもらって、マテリアルとテクスチャはデザイナーが管理すればいいという、とても素敵な座組みで作業を進めることが可能です。
これでアイコンを番号で指定して表示することができるようになります。
Blueprintから指定したアイコンに切り替えたいときに、set Scalar Parameter Value ノードが一つで済みます。
アイコンの種類を Int型で扱ってそのままFloat型にするだけというシンプルさと、UV値のことは忘れてもOKというのが魅力的です。配列変数のメンテやメモリも不要なのでプログラマも喜んでくれるはず。
ただし、このステキな方法にもリスクがあります。
UV座標をマテリアルで演算することになるのでGPU側の負荷になります。描画処理に余裕がない場合は控えた方がよさそうです。とはいえUIがガッツリ表示されている時はそれほどシビアな描画はしていないのがほとんどだと思います。
アイコン表示の切り替えでお悩みの紳士淑女のみなさま、ぜひこのマテリアルで計算する方法を一度ご検討されてみてはいかがでしょうか。
ではでは
今回はこの辺で
フォントのフチドリを試す
遅ればせながらようやく 4.14インストールできた。
なんといっても試してみたかったのが、フォントのフチドリ機能!
というわけでさっそくWidgetを作ってみる。
Designerモードで、Textblockを置いたところ。
設定を確認してみると、特に変化は見られない・・・
いろいろ開けていくとありました Outline Settings
サイズとカラーをセットしてみるとこんな感じに。
おおっこれは嬉しい!Epicさんありがとう!
私はてっきり、サイズ(太さ)を変えたりしたら、こうなるんじゃないかと期待していなかったのです。↓(同じものを8方向にずらして敷いているだけ・・・)
一人で盛り上がりつつ、
次にアウトラインマテリアルを試してみます。
作ったのはこんな感じ。
これをセットしてみます。
どうやら「乗算」ブレンドされるようです。マテリアルのままの色を出したい場合は、フチドリのカラーは「白」にしておくのがベスト。
マテリアルドのブレンドモードは特に違いはないのですが、Additive(加算)だけは描画されなくなります。(相変わらず加算の対応がよろしくないです。Epicさんよろしく)
Opacityにノイズ入れてみたらこんな感じ。
これにドロップシャドウを足してみましょう。
ドロップシャドウというか、もう一つ色違いのテキストブロックが描画されているだけですね。ドロップシャドウにもフチドリがつきます。
Separate Fill Alpha というチェックボックスがあったので試してみました。
アルファ値を「文字とは別」にするよ。というフラグのようで、
文字のアルファだけを0.0にすると下のようなこともできます。
Photoshopのレイヤーの塗り(%) で調整するのと同じ見た目が作れます。
気を付けないといけないのは、フチドリのサイズと文字のカーニングです。上図のxとtのところのように重なってしまいます。
あと、Separate Fill Alpha にチェックを付けると、フチドリと文字の間にスキマができるのが若干気になりますが、この機能はスバラシイです。
しばらくいじっているうちに、下のようなのができました。
テクスチャは使っていません。
ドロップシャドウのアルファ値は、0.0にすると、フチドリが消えてしまうので、0.001 というほとんど透明で見えない値を入れています。
このフチドリにマテリアルアニメーションを入れてみました。
↑GIFアニメで 700KB弱あります。
この動くフチドリをON / OFF すれば、カーソルフォーカスの代わりとして使えそうです。アニメーションのキーを打てないようなので、切り替える方法は今のところ思いつくのは2通り。フチドリのアルファ値を変えるのと、マテリアルのパラメータを変更する方法。
フチドリのアルファ値を変えるのは下のような感じでできた。
一度今のフォント設定を取り出したら、OutlineSettingsのとこだけMake FontOutlineSettingsノードで作った値に差し替えて戻します。
マテリアルで変える場合は下のような仕込みをしておいて、
マテリアルインスタンスダイナミックにしてアウトライン設定で差し替えておきます。
あとは普通にSetScalarParameterValue ノードでいじるだけ。
ひと手間かかりますが、パラメータを扱うときにスッキリします。
ちょっとキャプチャのコマを節約したので、ぎこちないですが動かすと下のような感じになります。
どうでしょうか。
まさかここまでできるとは思ってもみなかったので、すごくウレシイです。
改めて、Epicさんありがとう!
つぎは、マイターの種類が選べるようになるとか?
ではでは今回はこの辺で
ステキなフチドリライフをぜひ!
UE4でパーセント表記
戦績などのスコアを表示するリザルト画面や、武器やキャラのステータス表示で、「命中率」や「回避率」など「○○率」を表記することがよくあります。
この「○○率」を表示してやんよ~というわけで気軽にやってみたのですが、なかなかうまくいきませんでした。ははは。
例えば、命中率の計算。必要な情報は 『撃った弾数』と『当たった数』です。
基本的に『当たった数』を『撃った弾数』で割ればよいだけです。
100発100中なら100%と書けばいいのですが、300発100中ならどうなるでしょう。
100 ÷ 300 で 0.33333333333333333333333333・・・・
このように割り切れない場合があります。これを、33.33% と書きたいわけですよ。で、どうするか? 昔JavaScriptで覚えた方法を試します。
小数点以下2桁にしたい場合。
100 + 2桁のゼロ で 10000 まずは この 10000 を掛けてやります。
ゼロが4つで、小数点が4つ移動します。上の場合 5898.7654
掛けた値を四捨五入します。四捨五入した時点で小数点以下は消えるので、整数になります。この時点で、4桁の整数になっています。 上の場合 5899
それをさらに 100 で割ります。小数点が右端から2つ移動します。
PrintStringノードで表示してみます。
58.99 が表示されればバッチリです。
!
な、なんじゃぁこりゃぁ。2はどこから?
ネットで調べてみると、どうもイロイロ事情があって仕方のないものらしい。
コンピュータは基本 0 と 1 の2進数で動いていて、この2進数で小数点を表すことが苦手なようで、上のような微妙な誤差が生まれるとのこと。お金の計算でこの誤差はヤバいのでさすがにちゃんと対策されているそうです。なるほど小数点を扱うのは結構難しいもんですね。ふふふ。
いやいや。表示しなきゃいけないのですよ。
で、思いついたのが、四捨五入した時の Int型の値を、String型(文字列)にして分割してしまう方法。
整数同士の割り算は小数点以下を切り捨ててくれます。 上の場合 5899 ÷ 100 で 58。
うまくいきました。
ただこの方法だと、 必ず小数以下の2桁分がくっつけられるので、割り切れたとしても最後に0が付きます。
0.5 の場合、0.5 × 10000 = 5000 になるので、 50.00% と表示することになります。
なんか面倒な感じがして釈然としないので、便利そうなノードが用意されてたりしないかな、ゲームエンジンなんだし・・・と思いつつ探してみたらありました。
AsPercent ノード。
Epicありがとう!
Float型の値をパーセント表記に、しかもテキストで返してくれるというすぐれもの。
Text型ということは、UMGのTextBlock でサクッとと表示できて便利です。結果は、
おお!カンペキ! もっと早くに出会っていれば・・・(涙
右端の桁に 0 もつかないというシンプルさ。
ちなみに、小数点以下を固定の桁で四捨五入するのを「丸める」といいます。
AsPercent ノードの設定で好きな桁で丸めることができます。
Rounding Mode は丸める方法です。
ということで無事解決しました。
プログラマにテキストで頂戴って言えば、きっといい感じの関数を書いてくれそうですが、やっぱり表示する部分はUIデザイナーでも頑張ってみたいところです。
ではでは
今回はこの辺で
A と B を交互に切り替える処理でハマった話
TVのリモコンを握っている状況をイメージしてください。
TVが点いていない状態で電源ボタンを押すと起動して、点いている状態で押すと待機モードになります。
どちらの操作も同じボタンを押すことで切り替わります。
このように、A と B の2つの状態があって、一つの関数を呼ぶだけでスイッチングできないかなと思って試してみました。
実行するたびに、2つの処理を交互に切り替えたいので、引数で切り替えるのは無しです。
ようするに関数を単純に呼び出す(Call)だけでスイッチングしたいのです。
呼び出す側は「関数の中身なんか知ったこっちゃねぇ。」という状況が理想。
さらにシンプルなノードでできると尚良し。でやってみたのがこれ。
XOR ノード は 「排他的論理和」というやつで、同じものが来たら反転するというひねくれものです。違うもの同士は足します。↑の場合チェックボックスにチェックが付いている状態なので、
結果をすぐに変数にセットしてるので、内容が反転したことになります。
できれば変数を使わない方法でシンプルにできないかと思ってやってみたのがこれ。
結果はというと・・・
ここでようやくハマった話。
この MultiGate ノードを使ったつなぎ方は一度経験していて、当時はうまくいってました。で今回は「なんで?」となったのです。
結論を言ってしまうと、MultiGateノードは関数内に置くときは取り扱い注意 です。
単に「ランダムな結果を返せ」だったら is Random にチェックを付ければ問題ないです。今回のように上から実行ピン(Out 0 → Out 1 → Out 2 ・・・)を順番に流す場合はうまく働いてくれないことが分かりました。
関数の外に置いてみるとうまく働いてくれます。
Epicの公式ドキュメントにそれらしい記述が見つけられなかったので、当たり前の仕様なのか、バグなのかはプログラマじゃないのでなんとも言えないですが、ちょっと謎です。
もっとシンプルに切り替えるノードを思い出しました。FlipFlop ノードです。
「MultiGateはそういう仕様なんだ、でもFlipFlopなら状況を打開できるかも・・・」
と淡い期待を抱きつつ・・・
こちらも関数内に置いて使うと、Aのピンしか流れません。
外に出してみるとうまく動きます。
結局、外部から呼び出してスイッチングしたかったので、カスタムイベントにつなぐことで解決しました。
これでバッチリです。
ちなみにマクロの中で使う分には問題なく動作します。
ですが、そのマクロを関数の中に置くと、切り替わらないという結果になります。
あくまでも推測ですが、
切り替えるには、状態を保持しておく値が必要で、関数内からはその値が参照できなくなるんじゃないかと思ってみたり。
ではでは
今回はこの辺で。
ステキなノーディングライフを!
5分で作る マテリアルを使わないゲージ
超簡単お手軽ゲージを作ってみます。マテリアルは使いません。
Widgetブループリントを一つ用意します。
キャンバスに配置するパーツは3つ。
ゲージ用のキャンバスとゲージの下敷きは同じ大きさにします。下敷きは暗めの色にしておきます。
ゲージ本体の「Image」をキャンバスの子供にしたら、設定をサクッと変更します。
まずはAnchors(アンカー)を右下のやつに変えたら、
すぐ下にあるOffset関連の値をすべて0.0にします。
カラーを適当な色にしたら、
最後にキャンバスパネルの isVariable のチェックを入れて完成です。
編集モードをグラフに切り替えて、MyBlueprint のタブから、Function(関数)をひとつ追加します。
中身は以下。
コンパイルしてエラーがなければ保存して完成です。
レベルから確認してみます。
レベルブループリントを編集します。
再生してみると、
スペースキーを押すたびに長さが変化します。
完成です。
実際に時計見ながら作ってみたのですが、5分かからなかったです。
見た目には安いですが、このスピード感は大事です。
ゲージ一本でゲーム性やバランスが大きく変わるのはよくある話です。
ではでは
ステキなゲージライフを!
最近ハマったつなぎ方
ちょっとネタが無くなってきたのもあって更新ペースが落ちてます。
なので自分のウッカリでもさらしてみようかなと。
それは思ったような値にならず、原因も分からず、しばらく首をひねっていたつなぎ方です。
まずUMGでパーツを置いて、Widgetブループリントからいい感じにサイズを計算して調整しようとしました。
下図は 160x256 サイズの”Image”です。
これを、下のようにつなぎました。
計算した値を別のところで使いたかったので変数に保存しています。
ここで察しのいい方は気づかれていると思います。
Imageパーツのサイズをゲットして、タテ方向だけ1/16 にしてサイズを変更しています。
果たして、変数 Value の値はどうなっているでしょうか?
再生すると、パーツの見た目には うまくいっているように見えます。
でも、
答えは、 Value = 1.0 です。
え?
だって 256を16で割ったら16でしょ? なんで???
実際には 256 ÷ 16 = 16 したあとで、さらに 16 ÷ 16 = 1 となっているからです。
なんと割り算が2回計算されているのです。
SetSizeノードに割り算の結果が渡されたあとで、次は変数に値を渡すためにもう一度Imageパーツのサイズを取得して(このとき既に16になっている)16で割っています。
見た目に、割り算ノードのあたりで計算が済んでいるように見えるのと、同じピンから取り出してるので、同じ値が出てくると思ってしまったのが原因でした。
正しくは以下。
変数に値を入れない場合でも、値を確認しようとしてPrintStringノードをつなぐと・・・
1.0 という数値が表示されます。
PrintStringノードが値を表示しようとして、2回目の計算を行ってしまうためです。
では以下の場合はどうでしょう。
無事 16.0 という数値が表示されます。Imageパーツはというと問題なく 1.0 にならずに表示されています。
おそらくこれも2回計算していますが、PrintStringノードは、SetSizeノードのように結果を反映しないので、問題が起こらないのです。
この辺りのロジックが理解できるまでしばらくの間、首をかしげっぱなしでした。
以前に 乱数を発生させるノードでも同じようにハマったのを思い出しました。
例えば下のようにつないだ場合、
画面には、2つの異なる数値が表示されます。
以後気をつけます。
ではでは
ステキなノーディングライフを!