みつまめ杏仁

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

ゲージをテクスチャで増減させる

円グラフのように増減するゲージを作るとき、atan2(アークタンジェント2というプログラムの関数)をありがたく使わせてもらっています。少ないノードで実現できてしまうので、大変便利でありがたい存在。解像度に依存しないのもうれしい。ゲームで印象に残っているのはピクミン(2001年)かな。

原理的にはシンプルで、指定した座標と原点(0, 0)との位置関係を 角度 に変換してくれるというものです。なのでUV座標と atan2関数 を組合わせると下図のように変換することができます。

 

さらに Step や SmoothStepノードをつなげば円グラフゲージの増減が可能です。

 

アンリアルエンジンのマテリアルには ArcTangent2 というノードが用意されています。

そして便利すぎるのが VectorToRadialValue ノード。

このノードの中身を一部抜き出して整理するとこんな感じになっていました。


ただ、開発終盤の処理上げでこの atan2 が標的になることもしばしば。そこで前もって静的にテクスチャを作っておけばそれで対応できるんじゃないかということで、作ろうと思い立った次第です。

テクスチャのメモリ容量とその取扱いに対して atan2 の計算負荷、どちらが罪深いかはその時の描画面積やら描画状況次第ではあるので、どちらを採用するかは現場で判断することになります。

最初は作業時間優先で atan2 で作っておき、処理上げのタイミングで、テクスチャに差し替えたビルドと比較すると効果があるか、ないかが判明できると思います。

 

さてさて

Photoshopのグラデーションで、スタイルに 角度 というのがあります。

まさに atan2 を使ったような見た目のグラデーションが生成されます。

実際に使えるかどうか試してみたのが、Twitterに上げていた画像

ドキュメントのモードを RGBカラー と グレースケール 両方で試してみましたが、結果に目立つような差はありませんでした。

 

ということで、Processing を試すことにしました。。

最近だと SubstanceDesigner とかで作るのでしょうけど、AdobeCC の加入プランにラインナップされていないのもあって、昔お世話になった Processing を使うことにしたのです。

https://processing.org/

バージョンは 4になってました。

ジェネラティブアート界隈ではまだまだ活躍中で、コミュニティも多くそれなりに情報を拾うことができます。

この記事を書いているときもイベントが開催されていました。

Processing Community Japan

https://processing.jp/

 

マウスやキーの入力に反応することもできるので、インタラクティブな振る舞いも作って遊ぶことができます。

 

 

セットアップし、exeファイルを実行するとスケッチブックというエディタウィンドウが開くので、そこにスクリプトを書いていく。

言語は Javaをベースにしていて、JavaScriptに慣れていた自分としては、構文にすぐ馴染めるのでありがたい。

スクリプトを書くと、ウィンドウ左上の 再生ボタンをおすとすぐに結果が出る。

エラーがあれば、ウィンドウ下部のコンソールで教えてくれる。

無事エラーが出なければ、デスクトップにキャンバスウィンドウが新しく現れます。

 

void setup(){
  // キャンバスサイズ
  size(1024, 1024);
  // 背景色
  background(255,0,0);
  // 1回だけのDraw
  noLoop();
  // スムージング無効
  noSmooth();
}

void draw(){
  int dx = width / 2;
  int dy = height / 2;
  int x, y;  //描く座標
  float c;  //角度を明るさに
  //
  for(y=0; y < height; y++){
    for(x=0; x < width; x++){
      c = atan2(dy-y, x-dx) / PI// -1.0 ~ 1.0 にする
      c = c * 0.5 + 0.5;                 // 0 ~ 1.0 にする
      stroke(round(c*255));         // カラー
      point(x, y);                          // 点を描く
    }
  }
  save("image00.png");             // PNGでファイル書き出し
}

 

できました

描画し終えるとファイルに書き出すようにしています。

 

atan2 に座標を渡すときに、キャンバスサイズの半分の値を引くことで、0~1024だった座標の範囲を ±512 の範囲にずらしています。

上のサンプルでは、 X座標のところで、 x-dx としています。

これを dx-x に変えると UE5 と同じになります。

引き算の順番を変えると向きをコントロールできます。

あとからPhotoshopでテクスチャに書き出す際に回転すればいいだけなので、それほど気にする必要はないでしょう。ゲージの増減方向によって反転することもあります。

 

これをPhotoshopで開いて検証。

ヒストグラムもキレイ。うまく分布しているようなので安心。

できたPNGはサイズと向きを整えたらテクスチャに書き出してエンジンに持っていくだけなので、わざわざ グレースケールに変換する必要はないのだけど、一応グレースケールにしてみたら予想外の結果になった。グレースケールに変換した際に何らかのマッピング等補正が入るのかもしれない。

 

さっそくこのグラデーションを使ってゲージを作ってみた。

 

新たに以下のテクスチャを追加。サイズはどれも 64x64

グラデーションテクスチャは 256x256 にしました。

汎用という想定と、あまり小さいと、ドットのガビガビが目立つからです。

SmoothStepの扱いがちょっと雑ですが

残量によってカラーが変化するようにしています。

 

これに枠を重ねれば完成。

 

無事うまくいってよかった。

このリニアグラデーションテクスチャを使う方法は、いざ作るとなると手間ではあるけど、前もって作っておけば秘伝のタレのようにいつまでも使えるので、開発の初期や空き時間に用意しておくとよいかと。

 

シェーダーで atan2 を使う場合

  • 解像度を無視できるうえ精度が高い
  • 向きを変えるのはシェーダー内で
  • テクスチャが不要
  • 計算負荷が気になる

 

テクスチャを使う場合

  • 解像度に依存するので品質の制御が難しい
  • 向きを変えるのはテクスチャで
  • テクスチャメモリが気になる
  • 計算負荷が少ない

 

今回はこの辺で

ではではステキな円ゲージライフを!

 

 

最後におまけ

これも Processing で作れます。

距離を計算してくれる dist() という関数が用意されています。

端が斜めゲージの端っこ

ゲージの端が斜めになっているタイプの作り方について書いてみようと思います。

シンプルな四角形ではあるけど安っぽく見えないのがいいですよね。ただ両端の処理をちゃんとやってるか、やってないかでクオリティに差がでてきます。

 

アンリアルエンジンのUMGにはシアー(Shear)がプロパティとして用意されているので簡単に斜めにすることができますが、

何も対策をしていないと

アンチエイリアスがかからないので、ピクセルがガタガタになります。

ディスプレイの解像度が高くピクセルの物理サイズが小さければ目立たないのですけどね・・・

 

参考になればといくつかの方法を試してみました。

 

 

テクスチャを使わずシアーだけで作る方法

ゲージとして機能させるための簡単なシェーダーを用意します

これを Render Transform の Shear で傾けます

手っ取り早く絵作りと動きの確認をしたいときに使えると思います。
後日ブラッシュアップする時間を確保できれば問題ないかと。

当然ガビガビ。

 

 

 

シアーにテクスチャを使う方法

シアーで傾けるけど最小限のテクスチャで綺麗になるので、一番エコかもしれない。

シアーだけで作ってみたけど、やっぱり端っこのガビガビが気になった時にこの手法に切り替えるといいと思います。

テクスチャはこういったものを用意します。(横方向のゲージの場合)

ゲージの長さに合わせた長さで、両端を1ピクセルだけ黒にします。Grayscaleです。

高さは圧縮を考慮して 4 ピクセル

 

このテクスチャをゲージ本体のカラーとして、ゲージの形として使用します。

テクスチャの両端に隙間をつくる形になるので、前回の記事を参考に Lerpノードで余白を調整するようにしています。

ゲージの長さと、テクスチャの解像度に合わせて RangeMin と RangeMax を調整します。

テクスチャの端の1ピクセルは、表示される大きさによって細くなったり太くなります。

 

UMGのキャンバスに置いた Image に、このマテリアルをセットしてシアーで傾けます。

テクスチャを作りこむ時間が惜しいときや、アトラスに余裕がないときなどにおすすめです。

 

 

 

テクスチャで傾きを調整したい作り方

テクスチャに依存するのでサイズと角度が固定になります。またエンジンでの調整よりはテクスチャの更新が主軸になるので、分業体制なら能率の向上が期待できます。

 

テクスチャはこんな感じ。

まずはグレースケールでマスクとして使います。着色はマテリアルでやります。

シェーダーの原理は上のテクスチャを使ったシアーと同じ。ただ

上の例ではUV操作のところを変更しています。

Append と Add ノードの順番が違うだけです。

計算結果は変わらないので(正解と間違いとかではないのでご安心を)表現したい都合に合わせて使い分けるといいと思います。

UVを分解した方が後から細工がしやすかったりします。たとえばゲージカラーをグラデにするのが簡単です。

 

特に加工とかしないのが決まっているのであれば Vector2 にしてしまった方がスッキリします。

 

また、テクスチャサンプラーをパラメータにしておくとマテリアルインスタンスで差し替えができるので、シアーを使ったスタイルから移行するのが簡単です。

マテリアル内にテクスチャを直置きすると、マテリアルインスタンスを作る手間は減るのと、プレビューしながらノードを試せて便利なのですが、参照をガッツリ持ってしまうのがリスク。ゲームのUI は全体的に汎用性の低い仕様のものが多いので、パラメータを使わないケースがそれなりにあったりします。

といいつつもゲージについては汎用的に作れるケースが多いのも事実。プロジェクトの方針に沿って計画的に使い分けていきたいところ。

 

実は上下の端が薄くなるようにアルファ値を少し下げています。若干ボケた見た目になりますが、ゲージの表示位置が動くゲームだとこれがアンチエイリアスの効果を代替してくれたりします。

テクスチャならではのピクセル単位の調整ができるのがウリです。それなりに容量は消費しますが。

 

 

 

テクスチャを使わずに作る方法

テクスチャを使用せずシェーダーのみで作成するので解像度に依存しないのが強み。シェーダーを工夫できればどんどん表現を盛ることができる。計算負荷が問題になるかもしれないのでやりすぎに注意。

SmoothStepを使ってエッジをマイルドにしていますが、表示しながらマイルド具合を微調整するので、仕上がりはきれいですが、調整に時間がかかるのがタマにキズ。

上の例でもなかなかに細かい数値を入れています。

 

SmoothStepノードについての公式ドキュメントはこちら 

 → Unreal Engine の Math マテリアル表現式 | Unreal Engine 5.0 ドキュメント

 

 

ここから ややこしい部分をピックアップして解説していきます。

 

 

まずは SmoothStepノードのMin とMax の調整について。

 

何も調整していない場合

Min = 0.0

Max = 1.0

 

Min と Max を近づけてみます

0.5 を基準にそこから ±0.05 を Min と Max にする。

Min = 0.45

Max = 0.55

Min と Max がグラデーションの傾斜の開始位置と終了位置になります。

Min と Max の距離を調整することでシャープさを加減できて、離れるとぼんやり、近すぎるとガビガビになります。

 

 

次は 傾き について。

傾きは UVを分離して、片方に ±1.0の値を掛けて、足し算すると作れます。

下図は傾きをつくる部分だけを抜き出したもの。

グラデーションを Stepノード(X=0.5)で2階調にすると確認しやすいです。

 

Stepノード も SmoothStepノード も、グラデーションとは別の値を調整して全体の位置を変えることができます。

SmoothStepノードで便利なのが、 Min(最小値)とMax(最大値)を入れ替えるだけで反転させられることです。Stepノードでも可能ですがちょっとややこしくなりそうなので今回は説明は省きます。

 

 

次はテクスチャを使わないぶん、ちょっと手間が必要なのがゲージの両端を合わせる部分。

SmoothStep で 2つの見た目を作って計算して作ります。下図は引き算の場合。

黒が 0 、 白が 1.0 です。グレーはその間。

 

掛け算でも作れます。

上の図の B は、SmoothStepのMinとMaxを逆にすると作れます。

この合わせたやつを Alpha につなぐことでマスクとしてゲージの形となります。

 



 

いかがでしたか?

斜めゲージのシンプルな作り方をいくつか紹介しました。デザインと表現したい仕様に合わせて組みあわせていけばいろんなタイプのゲージが実現可能です。

エフェクト的なオーバーレイ表現や、満タンや空の時、チャージ中、段階、などなどアレンジを楽しんでいただけたら幸いです。

 

最後におまけで適当なゲージを作ってみました。

 

 

テクスチャはこんなやつ

(実寸)

256x32pxのテクスチャにして使用しました。

 

ブルーム(光彩の外側)は横方向だけ1/2サイズのテクスチャにして拡大表示。

(実寸)

288x64px サイズでゲージの後ろに配置。

 

テクスチャに高さがあるのでシアーは使っていませんが、後乗せのエフェクトやら装飾なんかでも使えるので工夫次第で盛りもりにできます。

 

斜めゲージの端っこの処理の記事でしたがゲージづくりのテクニックがそれなりに紹介できたので満足です。

 

ではでは

今回はこの辺で

素敵な ナナメゲージライフを!

 

四角いゲージばかりじゃつまらない

 最近はゲージを作るときにシェーダーを使う機会が増えました。表現の幅が広がって柔軟な調整ができるのが魅力です。ゲージはわかりやすさが大事ですが見た目が独創的であることもまたタイトルのユニークさをアピールできるパーツとして大事です。

 デザインはキャラクターに寄せるか、逆にキャラに依存しない方がいい、などと悩みながらデザインしていきます。デザインが出来上がったら次はゲームの仕様に合わせて状況に応じた変化をデザインします。空っぽ、満タン、バフ、デバフ、タイマーなどデザインに乗せるか、別途用意するか、エフェクトは、とか、とにかくゲージの数だけ表現方法、実装方法があります。

 そんな多彩なゲージを作るためには画像=テクスチャを使うことになります。

 

 テクスチャを使ったゲージを実装するときに悩ましいのが、たいてい上限と下限に「遊び」というか余白というかラグが生じます。UVで切り出す際、テクスチャの一部分を使うことが多く、また端をアルファチャンネルで削っているのが主な原因。

たとえばこんなテクスチャ

 

下図はアルファチャンネルの一部を拡大

 

バイリニアフィルタや表示位置によるピクセルの滲み(漏れ)を防ぐために、保険の意味合いでアルファを最低1px以上は空けておくのが普通。また、ピクセルのブロック圧縮形式のダメージを減らす目的で4の倍数(BCx系フォーマットで採用されているブロックサイズの標準が 4x4 なので)で領域を確保したり、UVの計算で割り切れるようにすると、自然と余白ができてきます。

将来的なデザインのブラッシュアップを考慮すると多少の余裕はあって困るものでもないかと思います。ただ描画面積が処理負荷を上げてしまうので、ご利用は計画的にというしかないのですが・・・

とにかく端いっぱいまでピクセルを使うのは、リスクがメリットを上回るのでおすすめしません。将来的にもっとナイスな圧縮アルゴリズムが出てきたら変わるかもしれません。

 

ところで、Photoshopでも小数点の位置を許容していますよね。

ピクセルグリッドにスナップ して用心して作っていても、ゲーム画面に描画される際に小数で扱われてしまうので、油断ならないのです。

 

 話が逸れましたが、まぁ「スキマはできるもの」として考えておけば、手間は増えても心配は減るということで、普段自分がやっている調整用のしくみを紹介することにしました。

 かなりニッチな内容です。ぶっちゃけ需要があるかどうかも怪しいですが、ゲージを作るところから書いていきますが、理屈の説明を多めで細かい操作方法は省いています。

 

まずはゲージの範囲について

ゲージには、空の状態と、満タンの状態が確実にあります。長さも絶対的なものではないので、視覚的にはだいたいの割合で視認します。あとちょっととか、半分くらいとか。

そのようなアバウトな感覚はパーセントで書く場合 0% ~ 100% の範囲で書くことになります。それを倍率計算に使う数値にすると、0 ~ 1.0 になります。

テクスチャのUV座標は、テクスチャの端から端までが 0 ~ 1.0 です。

そのままフルで使えたらラクなのですが、先に書いたように数ピクセルのスキマが存在します。そこを使わないようにしないと、満タンな見た目なのに、数値的には満タンじゃないという状況があり得てしまいます。

 

このギャップを吸収する必要があります。

 

それにはLerp(LineaInterpolate)ノードが便利です。

 

 

ゲームのロジックとしては数値は 0 ~ 1.0 で管理したいものです。ところがゲージはプレイヤーが直接目にする部分でデザインが重要。テクスチャの見た目に依存します。

今回はデザインの調整範囲がシンプルになるようにマテリアル内でギャップを吸収するかたちで進めます。

 

マテリアルには 0 ~ 1.0で値が渡されてくることになります。下図Scalarパラメータノード。

それを Alpha につないで、ゲージの端それぞれを A と B につなぐとこうなります。

A と B が 中途半端な値でもそれが両端の値になります。

上限と下限の値を自由に決められるということです。

テクスチャをインポートした後に、絵を見ながらこの上限と下限を調整すればいいのです。

 

 

とはいえゲージ

これをゲージとして機能させていきます。

まずゲージ部分の基本形

Lerpノードには外から変更する想定でScalarパラメータをつなぎました。

ゲージの増減方向によっては、Lerp の A と B は逆になることがあります。

 

名前は誤解されなければなんでもいいです。

 

RangeMin ・・・ ゲージのピクセル下限

RangeMax ・・・ ゲージのピクセル上限

GaugeValue ・・・ ゲージの値(しきい値

 

画像を使ったテクスチャは、ほぼこれでカバーできると思います。

ComponentMaskノードで

のみを有効にすると 横方向のゲージ、

のみを有効にすると 縦方向のゲージが作れます。

 

Stepノードで、0 と 1 の 2階調にしてます。

この2つの値をもとに、見た目を切り替えるようにつなぐとゲージが出来上がります。

ゲージの増減が下から上に向かって増えていくようにしたかったので、RangeMin と RangeMax を差し替えました。

 

0 と 1 で途中の段階はないですが Lerpノードで2種類の色をスイッチします。

マテリアルインスタンスを作って、テクスチャをセット

GaugeValueを動かすと

今回ゲージの背景を作ったのでそれを適用するようにしてみます

背景用のカラーをつないでいたところに別のテクスチャをつなぐイメージ。

今回同じテクスチャで、一定量ずらしただけなのでVectorパラメータで設定できるようにして下図のようになりました。

マテリアルインスタンスでずらす量をセット

動かしてみるとこうなります。

 

ここまでは普通にゲージを作る方法。

ここらはゲージの上限と下限を調整する方法。

 

まず調整する際に、マテリアル編集を気軽にできるかどうかで2つのケースを考えてみました。

※アンリアルエンジンでは「シェーダー」という表記をほぼ目にしない気がしているのですが、とりあえず当記事では「シェーダー」と書かずに「マテリアル」と表記していきます。

 

「編集はあんまり気軽じゃないぜ」というケース

すでにややこしいノードが組まれている、または組む想定で、触るのがリスクになったり、人が作ったマテリアルだからよくわからん、とか、そもそもマテリアルがよくわからんなどなど、であれば、調整用のパーツとゲージを別々に扱うのをお勧めします。

このケースではゲージ本体と同じ大きさのパーツを重ねるだけなので、お互い干渉しないつくりにできます。仕上げにパラメータの移植が必要になります。

 

 

「気軽に編集できちゃうぜ」というケース

経験上 ゲージはユニークで一点ものが多く、ゲージごとに調整する機会が多い印象。仕様に合わせてマテリアルも試行錯誤するので、そこにちょこっと調整用のノードを仕込んで一時的にパラメータを決めてしまおうというつくり。調整用のノードを外してもパラメータ自体はそのまま利用できるのが利点。

 

 

範囲を視覚化する

原理はシンプルで、上限と下限の値をStepノードで2階調に分け合算するだけ。

ComponentMask を R にすると、横方向にできます。

ノードのプレビュー用サムネイルでは赤と黒になっていますが、実際には Scalar(=Float=Vector1)型になっていて色という概念はありません。

ややこしい話ですが、ComponentMaskで R 以外をマスク、G 以外をマスクしたからといって、赤や緑色の情報が選別されて流れているわけではありません。Vector4(=Float4)の情報から1つだけを抽出してみてもただひとつの値があるだけです。そのひとつの値を視覚化する際にRGBA の 4つのチャンネルのうち 先頭の R から使われるので、赤色になると理解するといいと思います。 

 

編集はあんまり気軽じゃないぜ」という場合はこれを新しいマテリアルにします。

以降はこれのインスタンスを作ってそこでパラメータの調整を行います。

このコンテンツブラウザから上記マテリアルで右クリックするとインスタンスが作れます。

 

できたマテリアルインスタンスをUMGに持っていって調整します。

 

マテリアルインスタンスをセットしたImageを後ろに置きます。

サイズ同じにして位置を合わせたら、マテリアルインスタンスを編集して

保存すると反映されます。

あとはこのマテリアルインスタンスのパラメータをゲージ本体のマテリアルに移植(コピペ)すれば調整完了。この下に置いた調整用のImageを削除してお片付け終了。

 

 

気軽に編集できちゃうぜ」という場合は、調整用のマテリアルではなく、マテリアルファンクションにして持っていれば、ゲージを作るときにあちこちで再利用できて便利。この方法の利点は何といっても調整のしやすさ。

下図のようにカタチでマテリアルファンクションにします。

カラーは中に固定色として置いてしまってますが、お好みのカラーでOK。

都度変えたいのであれば、カラーも入力できるようにするといいですね。

 


このマテリアルファンクションをバイパスする感じでつなぎます。

ゲージの周囲にあるアルファで透明になる部分を利用しています。

マテリアルファンクションの右にあるName ノードは方向を確認しているだけなので実際は不要。

 

マテリアルインスタンスで確認するとこのようになります。

プレビューを見ながらいい感じになるようにパラメータを調整します。
リアルタイムに触れるこの方法は調整がしやすいのがウリ。

調整が済んだら、マテリアルを編集してバイパスした部分をお片付けします。

 

マテリアルのScalarパラメータにスライダーの設定があるので利用するとマウスでぎゅんぎゅん出来るのでオススメ。

Slider Max の初期値が 0.0 になっているとどこまでも数値が増やせてしまってマウスでぎゅんぎゅんできないので、1.0 にするのがポイント。



 

 

いかがでしたか?

これでどんなデザインのゲージでも大体なんとかなると思います。

何とかならないのは、増減が直線じゃないタイプ。とはいえ、テクスチャに合わせるなら、考え方は同じで、結局始まりと終わりで細かい調整が必要になります。

「あとちょっと!」 のあたりは実際に遊んでみてどれだけ視界に入るか、気にする必要はあるか、別のアピール表現と合わせてみようか、などなど試行錯誤しながら仕上げていきます。ゲージはゲームの進行に緩急をつけ、プレイヤーの心理状況にも作用する、とても重要な役割を担っています。なので、たかがゲージされどゲージ、世界に二つとない、万人に愛されるゲージを求めて切磋琢磨し、ゲージ道を究めんとするのが、UIデザイナーだと信じてやまない今日この頃、みなさまいかがお過ごしでしょうか?

 

ではでは今回はこの辺で

素敵なゲージライフを!

 

 

 

 

目パチの次は口パク

みなさんは BoxMask-2D ノードというものをご存じだろうか。

 

このBoxMask-2D というノードはUV空間に矩形を出現させるという恐ろしいチカラをもったノードで、どんなに精巧に作られたテクスチャであろうと、設定を間違うと全てを塗りつぶしてしまうこともあるという。

 

なにやら不穏な気配漂うノードだが、目線を消す処理やレターボックス風に使えたり、

と、上手く手なずけることができれば、それほど怖いものでもないかもしない。

 

ちょうど手元に目パチのサンプル用のキャラがあるので、口をぱくぱくしてみようと思い、この BoxMask-2D を試みることにした。

 

まずは、ベースとなるテクスチャ。

口も消え、さらにのっぺらぼう率上昇。

テクスチャ設定はそのまま

Mip Gen Settings : NoMipmaps

CompressionSettings  : UserInterface2D (RGBA)

Filter : Default

 

目は前回のを使うとして、今回は口のパターンを用意した。

パターン数は5

128 x 512px

テクスチャの設定は

Mip Gen Settings : NoMipmaps

CompressionSettings  : UserInterface2D (RGBA)

Filter : Default

各パターンのサイズは 128 x 80px

 

BoxMask-2D ノードの攻略をすべく、ワールドワイドウェブに情報を求めた。

そこで入手した貴重な情報によると、

ということらしい。

V2と括弧書きされているところは、Vector2型の値が必要ということで、UV空間での値になるそうだ。つまり 0 から 1.0 の割合で指定することになる。

 

口パクのテクスチャを作成した際に、切り出した領域をわかりやすくしておいた。

中心位置が分かるように、矩形の範囲を市松に塗り分けた。

矩形の大きさは偶数であることが好ましい。奇数だとピクセルを半分にできないからだ。

必要な座標は Photoshopでは選択範囲を使って簡単に調べることができる。

ドキュメント左上からの選択範囲の大きさが情報パネルに表示される。

ちなみに、選択範囲は飛び地になっていても問題はなく計測できるので、拡大してしっかりとピクセルの状態を確認しながら選択範囲を作るといい。

 

調べた結果。

 

これをUV空間の値に変換する。

UV値に変換するのは、テクスチャの大きさで割ればいい。

 

大事にならないことを祈りつつ BoxMask-2Dノードに必要な情報をつないでいく。

 

A には TexCoordノードをそのままつなぐ。

B のところには、Constant2Vector ノード(2キーを押しながらクリック)をつないで値を入力する。

X は U方向、 YはV方向に相当する。

入力フォームに 188/512 とタイプしてEnterキーを押すと、計算してくれるから大変助かる。

 

 

これで矩形の位置が合っているか確かめるために、あえて下のような状態のテクスチャを書き出して、エンジンのテクスチャを再インポート。

これが

↓こうなれば BoxMask-2D を制御できたことになる。

 

さっそくキャラのテクスチャに掛け算してみよう。

 

キャラのRGBに掛け算すると、こ、これは!

なんと恐ろしい。キャラが矩形で塗りつぶされてしまった。
いや、まて、アルファにはBoxMask-2Dの力は及んでいない。黒くなったということは、RGBに 0 が掛けられたということだ。ふと気づいて OneMinusノードを間に入れ、0 と 1 を反転するとうまくいった。

 

表示倍率を上げると、バイリニアフィルタによって、ピクセルの境界がボケて色のにじみが起こるので油断は禁物。

実際にテクスチャより大きく表示すると絵がボケるため普通はやらないから、等倍で表示して問題ないなら大丈夫だろう。
UV値に変換する手前、奇数にならないようにするのも大事だ。小数点で扱うため丸め誤差が出にくくなる。

 

この BoxMask-2D ノードを Lerp(LinearInterporate: 線形補間)ノードにつないでキャラと口パクの融合を試みる。OneMinusノードは計算量を減らすために外す。

 

結果は?

 

うまく2種類のテクスチャが融合したが、位置がおかしい。

そこで口パクの位置についてUV位置を補正する。

マテリアルの中で複数のテクスチャを扱う場合、UV空間は一つであるため、倍率を揃える必要がある。

 

キャラ絵は 512 x 512px、一方口パクのテクスチャは 128 x 512px と横が 1/4 しかない。そのままつなぐと横に伸びてしまう。

そこで、TexCoordノードの UTiling を 4.0 にしてアスペクト比を合わす。

当然タイリングするが、BoxMask-2D でマスクするので見えるのは1枚だけだ。問題ない。

 

あとは、これを適切な位置にずらせばいいだけだ。これも左上からのピクセル数を調べるとわかる。

この数値をテクスチャ解像度で割ればいいだけだが、横方向を4倍にしているため、124/512 とやるとずれてしまうのは少々ややこしい。正しくは  124/128 になる。口パクテクスチャのサイズの通りといえばそうなのだが。

 

UV座標空間の少数部分のみを視覚化すると下のようなイメージになる。

(普段使う領域は 0~1.0 の領域で、それ以外は暗くしてある)

U方向に4倍ということなので、0~4.0 の領域が圧縮されるかたちで表示サイずに収められるので、見た目にこのように視覚化される。

広角レンズで風景を撮ったのと似てるかもしれない。

画像サイスは一定なのに、広角レンズは視野角が広いのでより広い範囲を収めることができる。

 

右下方向にずらしたいので、マイナスになるように計算する。つまり、

U方向は、-124/128 =-0.96875

V方向は、 -198/512 = -0.38671875

 

0原点の場所が左上にずれるイメージで、結果として絵が右下にずれる見た目になる。

これは望遠鏡やカメラのファインダーから景色を覗くのに似ている。

この鳥を真ん中に捉えようとしたときのスコープを動かす向きをイメージするといい。

(対象の進行方向への移動は無視)

 

この位置補正を加えると、

 

よしよし、あとはパターンを切り替えられるようにすればOK。


パターン切り替えの計算を追加している部分。

この辺は目パチと基本は同じ。

Indexの値を切り替えることで、口パクのパターンが切り替わるようになった。

 

目パチは待機中の表現として常時動かすのは気にならないのだけど、口パクについては適宜タイミングを見て動かすほうがいいのでWidgetブループリントで試してみることに。

 

そのまえに、キャラ絵を元に戻して更新。

ひとまずテストとして、タイムラインからマテリアルのパラメータを書き換えてみる。

キーを打ってそのままだと、補間のタイプが Cubicになっている。

まるでスロットマシン・・・

キーの補間タイプを Conatant に変更。

全部を選んで右クリックするとメニューが出てくるので変更が可能。

 

Constant はキーの間を補間しないので、キーを打ったタイミングで書き換わることになる。

完成!

 

 

BoxMask-2D ノードでうまく部分書き換えができた。UV値の扱いが繊細なので、表示倍率が変わると隙間が出たりするから、調整に気を遣う印象があるけど、以外に使えるやつかもしれない。パーツの切り出しにきれいな値を使えば誤差も減らせるはず。

 

半透明にしてもきれいにフェードできそう。

Render Opacity を 0.5 にしてみると、

口は自然に薄くなってる。フェードに強いのはありがたい。

目は上に重ねているので、やっぱり明るくなってしまう。

 

 

初めて使ったノードだったけどうまくいってよかった。

ちょっと違う文体を意識してみましたがいかがでしょうか?

一息に書かないとブレるので難しいですね。

 

UV座標の計算については、職業柄 日常なので特に気にはならないのですが、慣れてない方に向けてちょっと丁寧に説明を書いてみました。

ゲーム開発においていろいろ効率化のためにもテクスチャアトラスを作るのは大事ですが、こういったアセットの制作にAIがうまいことやってくれる時代がそう遠くない未来にやって来るかもしれませんね。

 

ではでは今回はこの辺で

すてきな口パクライフを!

マテリアルで目パチ2

過去記事にコメントを頂いたので、アップデートの意味も込めつつさっそく試してみました

limesode.hatenablog.com

2パターンの絵を IF ノードを使って切り替えていました。(↓UE5で作成)

IFノードの A==B って判定がシビアで、個人的に観測をできた経験がないんですよね。

 

記事の終わりのほうで

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

などと無責任なことを書いてました。できないわけではないけども・・・

うぅ、ごめんなさい。

 

最近の IFノードには、イコールの判定に含めるためのしきい値が設定できるようになってたので試してみました。

テクスチャに RGB(128, 128, 128) のグレーを2か所に追加

        ↓           ↓

(x4)

 

IFノードの Equals Threshold を  初期値 0.00001 から 大きく 0.25に変更

3枚目のイラストが用意できなかったので無理やり着色して A==B に接続

あとテクスチャサンプラーノードの設定で、Automatic View Mip Bias を無効にして

ようやく観測できました。これで許していただけるでしょうか。。。

 

ただ調整内容が繊細な印象です。

一応 IF ノードを使わないのも作りました。こちらは2パターンのみですが。

Stepノードで 0か1 にして Lerpノードでスイッチしています。

 

 

さてさて

2023年です

UEもバージョン5になりました。

この目パチの記事はなんと2016年!実に7年前!!

 

ということで、自身の成長を確かめるべく、思い切ってパターンを増やす大作戦を敢行しました。

 

さっそくパターン制御用のテクスチャ 128x4px

(x4)

これがタイムラインの役割になります。

テクスチャの設定は

Mip Gen Settings : NoMipmaps

CompressionSettings  : Grayscale ※重要

Filter : Nearest ※重要

ピクセルが圧縮されると台無しなので、ピクセルが劣化しないようにするのが重要。

Nearest は、中間色が生じないようにするためです

 

イラストは新たに描き起こしました 512x512px

のっぺらぼうですね。

テクスチャの設定は

Mip Gen Settings : NoMipmaps

CompressionSettings  : UserInterface2D (RGBA)

Filter : Default

 

 

目パチのパターン数は4

256 x 512px

テクスチャの設定は

Mip Gen Settings : NoMipmaps

CompressionSettings  : UserInterface2D (RGBA)

Filter : Default

※各パターンの内側 1pxは透明にする等、バイリニア対策をしっかり

 

この3枚を使います

UMGで重ねるとこんな感じです

 

動いてるところ



ではマテリアルを見ていきましょう

あまり変わり映えしてませんね。

今回 重要なのがこの部分。

このグレースケールのテクスチャに使っているカラーは黒も入れた4色。

 

0~255(8bpp) の値 をシェーダーでは 0~1.0 に正規化して扱われます。

あえて分かりやすい値にしているために若干ズレが出ますが許容範囲ということにしたいのでこれを4倍して切り捨てると

0、1.0、 2.0、 3.0 になります。

これに 0.25 をかけることで、パターンを切り出すためのオフセット位置が得られます。

256 x 512px 解像度のテクスチャで、ひとつのパターンが 256 x 128 で計 4枚。

べき乗大好き!

UV の U方向は全部をそのまま使うので UTiling は 1.0。

V方向は 128 ÷ 512 で 一枚あたりの高さが 0.25 これが VTiling かつ、移動量。

切り出すサイズは、TexCoordノードの Tilingで固定しているので、上下に 0.25 ずつずらしていくとパターンアニメーションができます。

 

 

ブループリントは使わずマテリアル(シェーダー)だけで実現できました。

ランダム要素が入らない作りですが、テクスチャをタイムライン代わりにするので、ブループリントやマテリアルに触れない方でもテクスチャを更新するだけで調整ができるのがウリです。

 

 

少しは成長できてるんだろうか? いまいち実感はないけど、まぁそれなりに長くやってれば、という程度には慣れてきてると思う。

シェーダーは基礎だけならそんなに難しくはないと思う。何よりも大変なのは、アイデアを形にするまでの道のり。状況次第だけどいろんなやり方があって、複雑だけど汎用性が高いものもあれば汎用性はないけどシンプルに軽いのも作れたりする。この臨機応変さ個人的に好きです。答えは一つであってほしいという方には辛いかもしれませんね。

思い立ったらすぐに試すというのを繰り返すことが大事で、試行錯誤の回数が多いほど新しいアイデアへの扉を見つけるのが早くなると思う。

料理みたいなもので、いろんな食材と調理法を知っていれば自然とレシピなんかなくてもレパートリーが増える。

と偉そうなことを書きましたが 今回はこの辺にしておきます。

 

 

ではでは

ステキな目パチライフを!

 

 

スコアを表示する方法について試してみた

久しぶりに筆をとります

早いもので周りはもう新緑の候。88夜も過ぎ、滲みよる梅雨の気配を感じる季節になってますが、忙しくなると意識しなくなるというか、あえて意識から外しているところもあったりして、無理に季節感のあるコトバを並べてみたけど、なんか空々しい感じだな。

あ~早く暇になりたい。というわけで、ふと思いついて気になった表現方法を試してみたら以外に時間がかかってしまった件、自分としては一応解決を見たと思うので、記事を書くことにしました。

 

きっかけはYoutube動画で スコア表示のカウントアップ演出を見たとき。

前置きとしてフォントの話から。

最近普通に手に入るフォントのほとんどがプロポーショナルフォントなので、画面に文字を表示するとき、アルファベットの ” I ”(アイ)や ” l ” (小文字の L)のような字幅(余白も含めた)の狭いグリフは左右の字間が狭くなるように設定されているフォントをよく見かけます。数字の 1 も同様に狭く設定されていることが多い印象。

似たアルファベットと区別しやすくするためにセリフが強調されていたり、桁数を伝えることが重要なぶん、意図的に余白を広めにとって極端に字幅を狭くしないようにしているフォントもたくさんあります。とはいえ表示する桁数が増えると、 字幅の狭い文字や広い文字が同時にいくつも出現すると11111 と 88888 のようにチリツモで全体の表示幅が大きく変わってきます。

ただ画面に表示されているだけなら、それほど気にならなかったりしますが、リザルト画面やステータス画面などで、上下に並んだ時、桁数がわかりにくくなったり、カウントアップやダウン時に高速で書き換わるとガタガタと震えるように見えたりします。

 

サンプルとして上の3書体をエンジンにインポートして試してみました。

パラメータ増加やスコアアップなど変動時の演出を想定して 1000~9999 の間のランダムな数字を約0.1秒で表示更新してみると

桁は常に4桁ですが、文字幅の差次第で桁数が変わっているかのように見えてしまいます。

 

なるべく等間隔になるようデザインされたフォントを選ぶと、高速でカウントアップやカウントダウンをしてもガクガクと動くのは減らせるけど、それだけの理由でゲームの世界観に合うようにせっかく選んだお気に入りのフォントを諦めるのは悔しいです。

そういった時には、ひと桁ずつばらして個別に数字を書くか、昔ながらの方法でテクスチャにラスタライズして切り出して表示すると確実です。

ただこの方法は地味に手数が多いので、余裕がないときは手を出しにくいところでもあります。

 

そこで思いついたのが、

数字のテクスチャをタイリングさせてうまいこと計算してズラせばいい感じにスコア表示に使えるんじゃないか?

というもの。

 

すんなりと行かなかったけど、結果的にはうまくいきました

 

以下、いろいろ試すことになったその奮闘記。

 

まず数字を並べたテクスチャを作って

(32x512px)

 

これを、シェーダーでタイリングして

 

桁ごとに、縦方向にUVをずらせば・・・

 

さっそくワクワクしながら試してみた。

 

タイリングはUVを1以上の値になるよう乗算すればいい。

上の図だと U に4を掛けると以下のようにできる。

 

Uの値をFloorで切り捨てれば、Integer(整数)ぽく扱えるはず。

その 0~ の値と各桁の数字を紐づけられれば・・・・

はて?配列なんかあったっけ?どうする?

 

今の自分の知識では配列的に扱うのが難しいと判断してひとまず方針を変更。

テクスチャのタイリングをやめて、シェーダー内で重ねる方法を試しました。

見た目にいい感じの結果にはなりました。

 

透明とはいえ、表示面積を桁ぶん計算して重ねているので桁が増えるほど1ピクセルあたりの計算量が増えるので、正直使えないですね。

この方法を作ってみて感じた最大のメリットは、斜めになったフォントをいい感じに詰められるところ。

 

全体図

各桁をシェーダーで分解して、UVに補正値入れる仕組み。

ノードがいっぱいですが、桁分解以外は同じパラメータをコピペしてつないでいます。

UV補正はマテリアルファンクションを用意しています

 

Widgetに置いたときに、1マテリアルで済むので、Widgetブループリントはすっきりできます。

ただ、最終的な仕様が決まらない以上は、この手法は非効率です。

決まったとしても、8桁とか桁数が多くなると計算量が無駄に増えて負荷が心配になります。フレームレートに余裕があってGPUよりCPUが忙しいゲームであれば、逆に使えるかもしれませんが、そんなゲームあるのかな?

 

 

と、諦めの気持ちを引きずりながら ぼちぼち記事を書いてて、突然 マテリアルパラメータコレクションを使うことを思いつきました。まさに天啓。

マテリアルパラメータコレクションは、ブループリントから、マテリアルにパラメータを間接的に渡す仕組みです。

見た目に配列風なので、ひょっとしてと思い実験してみました。

 

マテリアルパラメータコレクションから値を取り出す専用ノードが用意されていますが、Name型で指定する仕様。

これだと配列的にアクセスするのは無理。

 

ここまでか~

 

とまた諦めかけたのですが、コードならひょっとしたら・・・

とひらめいたので最後の悪あがきを実行。

 

マテリアルパラメータコレクションの表示が配列っぽいのが気になっていたので、何かしらやり方があるはずと、簡単なマテリアルを作って、HLSLのコード化してみた。

 

Window > Shader Code > HLSL Code

を実行するとこんなコードが別ウィンドウで出力されるので、左上の Copy ボタンでテキストエディタにコピペ

パラメータの名前を検索してみるけど出てこず。

むむ・・・

 

そこで、マテリアルのノードを少し変更してコードを再出力。

先のコードと合わせて2つのコードをテキストファイルにして、WinMergeを使って差分を検出。

 

 

なるほど、こうやってパラメータを取得してるのか。

 

MaterialFloat4 Local1 = MaterialCollection0.Vectors[0];

 

ノードをいじりつつ、何度か出力を繰り返してわかってきた。

Vectors[0]は Float4なので、 Floatについては Swizzle演算子 を使って取り出している。

マテリアルパラメータコレクションに設定した Scalar型のパラメータについては、

Index[0] = Vectors[0].r

Index[1] = Vectors[0].g

Index[2] = Vectors[0].b

Index[3] = Vectors[0].a

Index[4] = Vectors[1].r

Index[5] = Vectors[1].g

Index[6] = Vectors[1].b

Index[7] = Vectors[1].a

という形で取り出せることになる。

 

5つ目以降については、4つごとに添字が1増える。

ということで、書き方を変えても

Index[0] = Vectors[0][0]

Index[1] = Vectors[0][1]

Index[2] = Vectors[0][2]

Index[3] = Vectors[0][3]

Index[4] = Vectors[1][0]

Index[5] = Vectors[1][1]

Index[6] = Vectors[1][2]

Index[7] = Vectors[1][3]

問題ないことが分かったのでCustomノードを用意。

このようなコードを書いた。

float num = MaterialCollection0.Vectors[int(V)][int(W)];
return num;

このカスタムノードでUVを整形。

数字は 8桁を想定。パラメータの Digits は桁数、Height は一文字ぶんの高さ。

右端の続きはサンプラーにつないでいるだけ

 

ちなみに グラフ内に

パラメータコレクションノードを一つでもつながないとエラーが出る。

ノードを単体で置くだけというのもダメ。

マテリアルパラメータコレクションをコード内でバインドする方法は調べ方がヘタなせいか見つけられなかった。

 

今回配列の順番がずれるのを嫌ったために、下図のような無駄な接続を作ってしまったけど、他に必要なパラメータがあれば、それをコレクションに置くことでスリムにできそうです。

 

これでよし。諦めなくてよかった!

 

さっそくWidgetで組み込んでみる。

ついでにHorizontalBox版も動かしてみる。

HorizontalBoxに入れたImageからDynamicMaterialInstanceを作って配列に入れる。

ForLoopが便利。

HorizontalBoxから取り出した子オブジェクトは一度 Image型にキャストが必要だけど、この処理でマテリアルを配列に入れておくことで、あとからマテリアルにアクセスするときはこの配列にアクセスするだけでOK。

HorizontalBoxのImageにセットしているマテリアルは以下。

シンプルに受け取った数に応じてUVをずらすだけ。

 

数字を各桁に分解して、マテリアルに反映するカスタムイベント。

ゼロサプレスしてます。

テクスチャのタイリング設定で、Y方向は Clamp にしておくと 「9」 の次に何もないので透明になります。X方向のみ Wrap にするのがミソ。

 

ゼロフィル(ゼロ埋め)の場合はBranchノードが不要になります。

 

値 % 10  というのは 10 の剰余を求めていて、例えば 123456789 という数だと、9 という数字だけにできます。一の位だけを取り出せます。

そのあと、元の数を10 で割ることで、一の位を捨てることができます。これは整数の割り算の特性で、小数以下は切り捨てられるのを利用しています。例えば 123456789÷10で 本当なら 12345678.9 になるところが .9 が捨てられるので、それを元の変数に戻してやることで、12345678 になり次に処理する時は一桁減った状態になっています。

受け取った数をいじりたくない場合はPower(累乗)を使用することになるかと思います。

Powerは整数では扱えないようなので、Float型にキャスト(型変換)が必要なのがちょっとアレな感じです。

ゼロサプレスしないのであれば、分岐はなくせます。

 

ForLoopの Indexを 7から引き算しているのは、HorizontalBoxの 子オブジェクトが 左詰めで、そのまま素直に配列にしてしまったのが原因。

あとあと全体に地味に効いてくるので、設計を吟味するのは大事ですね。

(次の画像↓ にあるSelectノードの左にあるピンの順番も、左から右の順です)

 

マテリアルに値を書き込むのは専用の関数を用意。(上図の中央付近)

この関数は両方のタイプに向けて処理してるけど、実際にはどちらか一方だけにする。

Option 0~7 でセットしているName型の名前はマテリアルパラメータコレクションで定義した名前になります。↓ 適当に追加ボタンを押した例

 

 

マテリアルに値を書き込むのは

HorizontalBox向けなら、SetScalarParameterValueノードで。

マテリアルパラメータコレクション向けなら、 SetScalarParameterValueで。

おっと、同じ名前ですね。

グラフ上で、"Scalar" と検索すると後者が。マテリアルノードからドラッグして検索すると、前者が取り出せます。

検索するとき Contex tSensitive のチェックを外すと 2つ同時に出てきます。

マウスオーバーでTipsが出るのでそこで判断するといいと思います。

 

あとは、用意した数字を桁分解してマテリアルに反映するカスタムイベントを呼び出すだけ。

テストとして、0.5秒おきに繰り返しランダムな数字を表示するカスタムイベント。

これで完成。

さっそくテスト

よかったよかった。ちゃんと動いた。

8桁だと尺が長かったのと、尺を縮めると数字が飛びすぎて面白くなかったので 0~123456 までのカウントアップです。

 

ちなみにカウントアップは Lerp(線形補間)を使ってます

カウントする時間を制御する変数をひとつ使いますが、変化量に関係なく一定時間で終わるようになります。

変化量が大きいときに便利ですが、逆に変化量が少なすぎるとのんびりした動きになってしまうので適宜補正が必要。

 

 

残念な反省文で終わるかと思った今回の記事ですがなんとか、それなりに形にできたので満足。

 

UIって意外なところで地味に手数がかかることが多いので、せめて作りはじめのスタートアップ時にさくっといい感じにできないものかと日々考えていますが、なかなか難しいですね。

 

今回、特段手数が減っているわけではないので、良い手法というわけではないですが、マテリアルと、マテリアルパラメータコレクション数字のテクスチャは、汎用アセットとして持ち歩けば結構便利なのでは?と思っています。

桁数を増やすのも簡単だし、何よりもレイアウトする時に、Image を一つ置くだけなのでレイアウト作業の能率が上がる気はします。

ただ懸念としては、マテリアルパラメータコレクションの扱い方です。

同時に表示する数字があると、マテリアルパラメータコレクションひとつだけでは足りないので、複数用意するかしないかになると思います。増やさない場合は中の Scalarを増やすことになります。

マテリアルパラメータコレクションを複数用意するとなると、マテリアルからの参照を切り替える必要がでてきます。Scalarの数を増やすと値の取り出しと書き込みの位置を慎重に管理することになります。

今のところ HorizontalBoxを使うのが一番無難でシンプルかもしれません。作業者のスキルと分業具合によっては効果があったりしないかなとか思いつつ、また何か思いついたら試していこうと思います。

 

ではでは今回はこの辺で

ステキなカウント表示ライフを!

 

 

補足というかおまけ

テクスチャアトラスを使わずにHorizontalBoxTextBlockを入れて使う場合の設定を載せておきます。

設定次第で、ガタガタしないようにできます。

 

下段は普通に追加しただけの設定

すべての桁が同じ設定なので、ヒエラルキーで複数選択すると一気に設定できます。

こちはら字間はPaddingで調整します。

 

上段は少し設定をいじっています

Auto を Fill に変えて、Horizontal Alignment を Center に変えるだけ。

こちらの場合、字間は Padding ではなくHorizontalBoxのサイズで調整できます。

 

テクスチャアトラス作るのダルいとかTextBlockのままで問題ない場合などに、HorizontanBoxはいいですね。

ただ、左詰めしか選べないのは残念。

Paddingにマイナスの値を入れれば右詰ぽくできましたが・・・・

 

以上おまけでした

 

 

謹賀新年2023

 このブログの投稿を 2015年12月20日に開始してから 7年 が過ぎました。年を重ねるごとに過去は長くなるので、振り返って見たときに割合としては短く見えるという感覚に改めて気づかされています。アンリアルエンジンを開発で採用する現場も増えてるのもあってか、UI制作向けというニッチな内容に注目していただいているのは喜ばしい限りで、手前勝手な内容で何かしらのお役に立てたなら書いた甲斐があったというものです。見に来てくださった皆様本当にありがとうございます。

 アンリアルエンジンのバージョンも 5 を迎えますますパワフルに進化して頼もしい限りです。UI開発においては大きな変革がなさそうな気配で慌てて記事を書かねばという流れにならなかったのはちょっと助かったなという感想。とはいえ技術的な内容は古くなると使えなくなるので更新し続けなければというプレッシャーも感じつつ時間を作って記事を書いていこうと思います。

 昨年はいよいよ本業のプロジェクトが本格的に動き出した年でおそらく今年がヤマ場。開発環境も変わってアンリアルエンジンを触る時間が激減し、気づきを得る機会も減り、結果的にここ最近の記事の少なさにつながっているのをなんとなしなければと、DIYでパズルゲーム的なものを作り始めました。体力的にリリースまで漕ぎつける気がしないですが、ネタを見つけて記事にしていこうと思います。

 ゲーム開発は長丁場なぶん体調管理が重要です。今年は特に大事な年なので気を抜かないようにがんばります。みなさまもお体を大事にお過ごしくださいませ。

近所の寒桜 ↑

 

ではでは

ステキな一年になりますように