みつまめ杏仁

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

キーリピート機能をつくってみる

 パソコンでキータイプしていると気づくこともあると思いますが、カーソルキーとか同じキーを押しっぱなしにしたときに、1文字目と2文字目の間にちょっとだけ間があります。タン、タタタタタタ・・・・・・ 初めてパソコンを触ったとき、当時子供だった私はモヤモヤした経験を覚えています。UIを意識するようになってようやく腑に落ちたものです。

f:id:hiyokosabrey:20180204094046g:plain

 ゲームでも、音量調節のスライダーなんかにごく当たりまえに実装されているので、身近なやつを見れば・・・って、最近はタッチデバイスなのであまり身近じゃないですね。でもまだPS4とかゲームパッドで遊ぶUIはあるので、今回ブループリントで作ってみました。

 

UMG

キーリピートの挙動を見るために、シンプルなボリュームスライダーを用意します。

キャンバスに3つのパーツを配置します。

f:id:hiyokosabrey:20180203125755p:plain

f:id:hiyokosabrey:20180203125802p:plain

右端がMAX想定なので、ツマミは左端に置きます。

 

ブループリントから触るので3つとも Is Variable にチェックを付けます。

f:id:hiyokosabrey:20180203130034p:plain

触るといっても、Image_Baseだけはサイズを取得するだけです。

 

 

Widgetブループリント

変数を2つ用意します。

f:id:hiyokosabrey:20180203130610p:plain

 

まずは、スライダーの移動範囲を調べて変数に入れます。

f:id:hiyokosabrey:20180203131734p:plain

すでにキャンバスに置いているパーツの長さを調べるので、Event Pre Constructで問題ないです。Get Size で調べたImage_Base(ラインみたいなやつ)の長さを変数 MaxPos に Set します。これは、後からデザインやレイアウトが変更になっても、キャンバスを調整するだけ(Blueprintは無傷)で済むのでオススメです。ひと手間かかってますが、こういったつくりは後で地味に効いてきます。

 

次に関数を2つ用意します。

まず一つ目は指定した値の場所にツマミを移動して、値を表示する関数になります。

f:id:hiyokosabrey:20180203132503p:plain

便利な Lerpノードを使います。AとB2つの値を線形補間したうえで、Alphaの値に応じた途中の値を返してくれるノードで、MaxPos を Bのピンにつなぐことで、どんな長さのスライダーでも対応できるようになります。MaxPosはパーツの長さを調べてるのでデザインが変更されても、勝手にこのBの値が変わっていることになります。

 

 もう一つは初期状態の値をもらう関数です。

f:id:hiyokosabrey:20180203193152p:plain

 ゲームでは設定した値をセーブしているのが普通なので、まずは初期値を受け取れるように関数で用意します。この int型の Value という変数は、念のため Private にチェックをつけておくと安全です。

 

関数が用意できたら、今度はマクロを用意します。

受け取った値を Valueに加算して、0~100の範囲を越えないようにします。

f:id:hiyokosabrey:20180203193901p:plain

越えたらループするようにしています。

減っていくとき、3 → 2 → 1 → 0 → 100・・・

増えていくとき、98 → 99 → 100 → 0・・・

このWidget以外から呼ばれる処理ではないので関数ではなくマクロにしました。

 

仕上げにイベントを用意していきます。

カスタムイベントを2つ置いてマクロと関数をつなぎます。

f:id:hiyokosabrey:20180203194836p:plain

引き算のノードを使わなくても、マイナスの値は、足し算することで引き算と同じ結果になります。汎用性の高いマクロや関数を作るときに応用できます。

 

Widgetは完成です。

次は動かすためにレベルブループリントを編集します。

 

 

レベル

おなじみのやりかたでWidgetをViewportに追加すると、表示された瞬間EventConstructが動くので、先に初期値を渡しておきます。

f:id:hiyokosabrey:20180203195847p:plain

試しに再生してみると、

f:id:hiyokosabrey:20180203200040p:plain

ちゃんと反映されていればOK。

 

 

では、キーリピートの処理を作ります。

必要な変数を用意します。

f:id:hiyokosabrey:20180203225924p:plain

まず、float型の変数は、キーリピートの間隔を保持します。スライダーが増えるか減るかをフラグで管理するためにBoolean型の変数を。一番上の RepeatTimerHNDLという名前の変数はTimerHandle型の変数で、Set TImer Event ノードの戻り値 Return Value ピンからPromote to Variable すると簡単に作れます。

 

カスタムイベントを用意して、下のようにつなぎます。

f:id:hiyokosabrey:20180203230620p:plain

右端のノードは、Widgetに作っておいた関数を呼び出しています。増えても減っても基本的なキーリピート処理は変わらないので、極力使い回せるものは使い回すようにしています。

続きはこのようになっています。

f:id:hiyokosabrey:20180203231752p:plain

 DoOnce ノードでキー入力初っ端だけ通すようにして、2回目以降のリピート間隔を float型の変数にセットしています。

 

まだ続きます。DoOnceはリセットすることができるので、キー入力をやめたらリセットするようにつなぎます。下図はカーソルキーの左右を押した場合です。

f:id:hiyokosabrey:20180203232534p:plain

 

これで完成です。

さっそく 動かしてみましょう。

f:id:hiyokosabrey:20180204084434g:plain

キー入力を開始して、ひと呼吸置く感じで動きます。

 

基本的な仕組みはイベントの自己呼び出し。 f:id:hiyokosabrey:20180204085027p:plain

あとは、DoOnceノードで、RepeatInterval 変数の値を 0.75 から 0.025 に変えます。

これでキー入力後の《 間 》が作れたことになります。この値は 1.0  が1秒です 。フレームレートによりますが 60fpsだと、0.0167 くらいで 1フレーム分です。これを変えてみるといい感じに調整できますよ。

 

この《 間 》が無いとどうなるか、0.75 をセットしてるとこを 0.025 にしてみると答えが分かります。

 

次回は、せっかく作ったスライダーをいくつか並べて操作できるようにしてみようと思います。

 

ではでは

ステキな キーリピート ライフを!

 

UIデザインというお仕事

 気がつけば2018年の12分の1が終わってちょっと焦り気味な今日この頃。残り少ない平成時代を精一杯堪能したいと思うんだけど、何をすればいいか思いつきません。あ、平成30年発行の硬貨を記念に取っておくとか?

それはさておき

2018年最初の記事は雑記で始めてみたいと思います。画像もなんもなく文字だらけなうえにテクニックとか有益な情報はないので悪しからず・・・

とりあえず、UIデザインというお仕事について、私なりに感じている事を書いていきます。

 

自分のこと

 私がゲームのUIを作る仕事に携わってかれこれ四半世紀。UIという言葉がまだなかったころから活動しております。最初は専門職という認識は誰にもどこにもなく、新人や比較的手の空いたメンバーが担当するのがUIだった時代です。

 最近では専門職としてブイブイ言わしてもらえ・・・てはいないですが、一応専門職ということになっております。今までにいろんなUIを作ってきました。「作った」と言っても一人で作れるわけはなく、私はデザイナーなので実際はプログラマとの共同作業です。

 アーケードゲームの開発から始まって家庭用のコンソール機用ゲームと多くのタイトル開発に携わっていろんなことを学びました。 今やアーケードゲームはほとんどが音ゲーや特殊な大型筐体ばかりになってしまいましたが、このアーケードゲームにおいてのUI開発はとても多くの示唆を与えてくれました。その知見が今でも十分に役に立っています。このへんのノウハウはうまくまとめられる自信がないので、今後それとなくこのブログに散りばめていこうと思っています。

 

ゲームのUI

 先に書いた通り私はゲームのUIを専門にしています。ゲームのUIというのはゲームという面白い遊びに、ユーザーを引き込んでコミュニケーションするためのもので、ユーザーとゲームシステムがコミュニケーションするためのインターフェイスのことを指します。「インターフェイス」という語についてはニュアンスをうまく伝えるのが難しい語なのですが、平易な書き方で「やり取りのための仕組み」くらいがゲームUIとしては一番近いニュアンスかなと思っています。そのUIを考えるうえで外せないのが「時間」の扱いです。

 

プレイ時間とUI

 ゲームにはユーザーがプレイし始めてから終了するまで、という「時間」があります。この「時間」はとても重要で大変貴重なものです。もちろんUIにとっても。

 昔のアーケードゲームでは単位時間あたりのインカム数(コイン投入数)がビジネスとして重視されました。プレイ開始から、いかに短時間でプレイヤーを満足させるか、またゲームオーバーになっても、コンティニューしたくなるようにするのが課題でした。そのためにはキャラクター選択や必殺技のデモ演出というようなゲームプレイ(体験)とはあまり関係ない画面はインカム数にダメージを与えるとして、徹底的に切り詰められました。とにかくパッと見て必要な情報をシンプルに分かりやすく配置し、短時間に何をどう操作して決定させるかが、UIに課せられた任務でした。100円で満足するには、UIではなくキャラを操作したいですよね。

 残念ながら、どれだけ素晴らしいデザインのキャラセレ画面やアイテム管理画面なんかを操作しても、それを思い出として語るプレイヤーはなかなかいませんし、ゲームをプレイしたという思い出にUIは含まれないものと了解するしかありません。空気のような存在感のUIでユーザーがゲームプレイに満足できれば、そのゲームのUIは素晴らしいUIである。と本気で思っています。

 

 ちなみに「GAME OVER」という表示は、アーケードゲームならではの演出です。その理由のひとつとして、ゲームセンターという公共の場所にカギがあります。乱暴な書き方をすると、ゲームオーバーの文字が表示されたら、さっさと席を譲れ。ということです。あなたの100円でのプレイ可能時間はここで終わったんだよ、と。

 

 アーケードゲームに限らず、このプレイ時間(アプリの場合は操作時間)というものは、プレイする側にとっても、プレイさせる側にとっても大変重要な要素であることは疑いようもなくて、ここの意識が弱いと、必要な操作なのに分かりにくくてモタついたり、目的の状態まで進めていくのに演出の尺が長いといった、テンポの悪いUIを許してしまう恐れがでてきます。

 

 そういえば、UIを操作している時間が貴重であることに気づいた偉い人が、何年か前にUX(ユーザー体験)という言葉をハイライトして、ユーザーがよりシンプルでスマートに目的を達成するためのUI設計を考えましょう。と提案したことで「UI/UX」というパワーワードが俄かに脚光を浴びることになったのだと思っているのですが、ゲームセンターでの教訓を学術論文にでもして発表できていれば、ゲームの世界からUI/UXが語られていたかもしれません。

 

 さてさて、この「時間」というものを意識してUIを考えると、ただグラフィックがそこにあるだけではUIは成り立たないことに気づきます。グラフィックの存在と合わせてそのグラフィックの行方をどうするか、がUIを作るうえで重要になってきます。

 

振る舞いと意味

 ゲームシステムからUIを通じて選べと言われてユーザーは選んで決定し、ゲームシステムはその情報を元に次のフローに進みます。このゲームシステムとユーザーとの対話がスムーズに進むようにするのがUIの役割です。ユーザーに不安を抱かせないように気つけながらいろんな手段でユーザーに選択を促しその結果をフィードバックします。この時の対話で何らかの動き=「振る舞い」を使うとやり取りの効率がぐっと上がります。

 分かりやすいのは決定した項目をハイライトしたり、カーソルを点滅させたりとかです。UIとして画面に表示されるグラフィックはすべて、必ず何らかの振る舞いを持ちます。「意味を持つ」と言い変えてもいいでしょう。パッと出て、パッと消えるのも振る舞いです。ユーザーの目に触れてから消えるまでの存在すべてが振る舞いであり、ユーザーへ伝わる「意味」となるのです。

 動きには当然時間が伴います。時間といっても非常に短い時間ですが、この小さな動き=振る舞い(新しい言葉でマイクロインタラクションとでも言えばいいのでしょうか)がつながってゲーム全体のテンポに影響を与えます。

 

UIデザインというお仕事

 だいぶ回りくどい感じになってしまいましたが、ようやく表題に近づいてきました。

 UIはメタで抽象的な世界から答えを見つけてきて表現することが多いので、「正解」というものはいくらでもあります。その中から「Bestな正解」を、ワインのソムリエのごとく見つけてきて開発チームに提案します。それが受け入れられれば幸せですが、受け入れられなければまた数多の正解の中から次の正解を探す旅に出ることになります。ステージに草を生やしたい。と言われれば草に見えるものを置けばいいのですが、UIにはゲームシステムからの情報伝達という大事な役割があるので、そういった具象的なものをそのまま置くだけでは意味が伝わりにくいです。ユーザーにUIとしての存在意義を疑われたらおしまいです。齟齬やミスリードの無いように慎重に設計する必要があります。どういったタイミングで、どういった情報をユーザーに伝えて判断を促すのがいいのか、どういった振る舞いをすればゲームシステムとの対話になるのか、どこまでが装飾であるのか、こういった部分をひたすら考えます。

 振る舞いも含めてデザインするためには、何らかの動き(アニメーションなど)を検証するところから始めて、Bestな正解を探します。光り方や点滅速度、移動の方向や速度など、ある程度はAfterEffectやDCCツール、Flashなどタイムラインの仕組みを持つツールがあれば検証できますが、それはあくまでもシミュレーションにすぎません。やはり対話には「コール&レスポンス」の心地よさが大事です。そこを実際に動かすことができるのは、ソフトウェアとしてのプログラムということになります。UIパーツの振る舞いを考え、それをプログラマに伝えて組み込んでもらいます。

 動いたら触ってみて感触を確かめます。手触りの悪いところは調整しつつ、仕様要件を満たしているか、また将来追加される仕様に対応できるかなども確認します。こうして限りなく製品に近いモックアッププログラマと一緒に作って、レビューしてもらうのが理想形です。

 プログラマに面倒な動きをお願いしたり、レビューの意見に振り回されたりしつつも二人三脚で作っていくのがUIデザインというお仕事の基本になります。このあたりの具体的なテクニックやノウハウなども、機会があれば書いてみようと思います。

 

 アンリアルエンジン推し

 UIをデザインしてモックアップを作る環境が理想なのですが、そこにはプログラマが必要です。絵にかいた餅を食べられるようにしてくれるのがプログラムなのです。デザインして食べてみておいしいかどうか。これを繰り返してUIデザイナーという職能(=スキル)を高めることができると思います。一人でUI開発するのは難しいです。振る舞いをどうにかしてくれるプログラマの存在が欠かせないからです。

 ただ画面のイメージ画を作って見せても、いまいち具体的な操作感や振る舞いをイメージしてもらうのは、頭の中でシミュレーションできる人じゃないと難しいです。

 

 なんとかして動くものを見てもらいたい、そのための研究としてOff-JTしたいなーと思っていたところにアンリアルエンジンと出会って、すっかり魅了されてしまいました。シンプルで柔軟なアセット管理ができるのも分かりやすいし、作ってみたいUIをすぐに試せる気軽なUMGとWidgetブループリントはもう手離せません。プログラマにお願いする前にプロトタイプを作って検証できるのがとにかく素晴らしいのです。アイディアを形にしやすいのがアンリアルエンジンのビジュアルスクリプトだと思っています。ブループリントの魅力は触ってみて実際に作ってみないと実感しにくいので、言葉で説明するのはやめておきます。UI的にどんなことができるかは、当ブログの記事で確認してもらえればと思います。まだまだこれからも頑張って紹介していくので、興味が沸いてきたならぜひ触ってみてください。

 

  結構な文字量になってきたのでこの辺で筆を置こうと思います。(←古風な言い回しですがこの表現好きです)

 UIデザインって実はとても大変なんです。グラフィックデザインを学んだからといって一朝一夕でできるようなお仕事では決してないことを言いたいがために、時間と振る舞いに重点を置いてみたのですが、いかがだったでしょうか。長くこの仕事をしていると、一家言どころか、百家言くらい言いたいことがあったりするのですが、こちらもまた別の機会にします。感想やらツッコミなどありましたらコメントとかでよろしくお願いします。

 

ではでは みなさん

ステキなUIデザイナーライフを!

今年も当ブログをよろしくお願いいたします

 

 

よいお年を

ついに大晦日ですねぇ。このブログもペースは落ちてますが、なんとかマル2年続けることができました。これも多くの方に読んでいただいているのが、励みになっています。ありがたや、ありがたや。

2年も経つとエンジンのバージョンも随分アップデートされてきました。そろそろ過去記事をメンテした方がいいかもしれないなぁ と思うんだけど、それよりも新しい記事書かないと、という想いがその思いを押しやってしまって結局のところネタを思いつかなくて筆が重くなるという、よくわからない悪循環のような状態になっている今日この頃です。大晦日ということで、小ネタを載せて2017年を締めようかと思います。

 

マテリアルで絵を揺らします。パラメータで制御できるので、いい感じにアニメーションさせればそれなりに使い途はある・・・と思いたい。

f:id:hiyokosabrey:20171231203820p:plain

制御用パラメータは3つ。

  • Period ・・・波の数
  • Amplitude ・・・ 左右の振れ幅  0でまっすぐ
  • OffsetY ・・・ タテ方向のスクロール用

 

真ん中のシマシマのテクスチャは、こんなやつ。

f:id:hiyokosabrey:20171231204249p:plain

8 x 512px のグレイスケールテクスチャです。

あとは、タイムラインからパラメータ用の数値を取り出して、横流しをしてやればOK。

アニメーションを再生して、

f:id:hiyokosabrey:20171231205515p:plain

 

EventTick で取り出して横流しです。

f:id:hiyokosabrey:20171231205555p:plain

この例では、最初からある キャンバスパネル の Pivot は演出に使わないので、Pivot にアニメーションを仕込んでいます。Pivotは XとYの2つしか値を持っていないので、 OffsetYとして 0.5を掛け算して 再利用しています。

 

アニメーションを再生するカスタムイベントが呼ばれると動きます。

f:id:hiyokosabrey:20171231210729p:plain

f:id:hiyokosabrey:20171231210739p:plain

f:id:hiyokosabrey:20171231210747p:plain

うにょ~んと動くので、なかなか楽しいです。

動画でお見せできないのが残念ですが、興味を持っていただけたならぜひ試してみてください。

どこで使うんだろうというネタですが、これで今年は締めさせていただこうと思います。

 

ではでは

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

ステキなUE4ライフを!

 

マテリアルで電光掲示板を作ってみる

オモムロに電光掲示板(流れるやつ)を再現してみたくなって試してみたら、なかなかいい感じになったのでメモっておくことにします。

f:id:hiyokosabrey:20171215214252p:plain

 

たまにゲームで見かけるのが、ドット風のテクスチャでマスクされて、UVスクロールしているやつ。穴のたくさん開いた板の向こうを看板が滑っているようにみえるので残念な気持ちになることがあります。まぁこんなところが気になるのは職業病ですね。

 

・・・

 

 まずテクスチャを用意します。

 

f:id:hiyokosabrey:20171214231224p:plain   ←256x16 px

 

フォントはアンチエイリアスを無しにします。Photoshopの書式設定は以下のとおり。

f:id:hiyokosabrey:20171214231500p:plain

 

UE4のインポート設定は GrayScaleにします。ここで重要なのがフィルター設定。

f:id:hiyokosabrey:20171214231748p:plain

 拡大表示してもドットがボヤけないように、Nearest にしておきます。

 

できたテクスチャを使ってマテリアルを用意していきます。

f:id:hiyokosabrey:20171215200359p:plain

 テクスチャの一部を切り出す(トリミング)ので、TexCoordinateノードのタイリング設定は以下。

  • UTiling: 0.25
  • VTiling: 1.0

これで256x16のテクスチャの内、 64x16 (タテヨコ比 4:1)の部分が目に見えることになります。

Add ノードで値を追加すると、UV値が移動します。そこで移動用の仕組みが以下。

f:id:hiyokosabrey:20171215202244p:plain

Time ノードは、Period という設定値を持っていて、値を設定しておけばその値までカウントしたらまた 0 に戻って・・・を繰り返します。ここではテクスチャサイズを入れておけばいいのですが、カウントアップの速度がそのままスクロールスピードになるので、いったん 1/10 した値を入れておきます。すると、 0.0 → 25.6 でループします。

そしてその値を 10倍することで、 0.0 → 256.0 にできます。

このあとの Floor ノードの手前で 0.0 ~ 256.0 という値になっていれば問題ありません。

さらにスピードアップするなら、 Period = 2.56 で 100倍すればOK。

この状態で見た目にそれっぽくなります。

下はWidgetのキャンバスに Image パーツを置いてマテリアルをセットした状態。

f:id:hiyokosabrey:20171215203515p:plain

パーツのサイズは 1024x256 です。 テクスチャのフィルタ設定を Nearest にするとピクセルがボケずにそのまま拡大されるのが分かると思います。

 

もう少し雰囲気を出していきましょう。

タイリング用のマスクテクスチャを用意します。

 

f:id:hiyokosabrey:20171215203905p:plain  ← 16 x 16 px

 

これをインポートして、先ほどのマテリアルに持ってきます。

f:id:hiyokosabrey:20171215204144p:plain

Multiply で掛けるのですが、そのままだと、↓こうなるので・・・

f:id:hiyokosabrey:20171215204345p:plain

TexCoord先生にタイリングをお願いします。

  • UTiling: 64
  • VTiling: 16

Tilingの値は、1.0以上の場合は、言葉の通り繰り返し回数なのでイメージしやすいですね。

f:id:hiyokosabrey:20171215204714p:plain

いかがでしょうか?かなりいい感じになったと思います。

 

今回のマテリアルはWidget専用というわけではないので、いろいろ応用できます。 

せっかくなので、マテリアルドメインを通常の Surface にしてシリンダーに貼ってみました。

(文字テクスチャの部分切り出しは無しにしています)

Emissiveの値を強めておいて、ポストプロセスでBloomを有効にすると雰囲気アップです。

f:id:hiyokosabrey:20171215211616p:plain

 

 

 

マスクテクスチャのデザインを変えると、ちょっと雰囲気を変えることができます。

f:id:hiyokosabrey:20171215210442p:plain ← LED風

f:id:hiyokosabrey:20171215210504p:plain←ブラウン管風

この色付きのマスクの場合、文字のカラーを変えるといい感じになるのでオススメです。

でちょっと遊んでみたのが冒頭のやつです。

f:id:hiyokosabrey:20171215214252p:plain

かなり雰囲気が出せました。

 

 

タイリングの回数が多くて処理が・・・となるのであれば、マスクテクスチャをあらかじめいくつかタイリングした状態にすれば、回数を減らすことができます。

テクスチャの容量は増えますが、描画の負荷は減ります。

f:id:hiyokosabrey:20171215212135p:plain ← 32 x 32 px

  • UTiling: 64  → 32
  • VTiling: 16  → 8

 

 

今回はこの辺で。

ではではステキな電光掲示板ライフを!

 

 

2枚の絵をマスクで切り替え

このブログもそろそろ2年目を迎えます。よく続いたもんです。さすがにネタに困ってきてる気がしないではない・・・というかちょっと困ってます。

朝、駅のホームで突然ひらめいたりしますが、地下鉄の駅から地上に出たところでスッカリ忘れていたりするので、もうどうしたものか・・・。

 

さてさて

そんな ネタ貧困生活のなかでようやく思いついたのがマスクテクスチャを使った絵の切り替え。どこらへんに需要があるか分かりませんが、工夫次第で面白い表現が出せそうです。

 f:id:hiyokosabrey:20171206041405j:plain

 

ではまず

マスクテクスチャを作ります

解像度はかなり小さく作ります。

40x23 px  ↓これは400%に拡大した状態

f:id:hiyokosabrey:20171205212853p:plain

ノイズを乗せます。このときヒストグラムが確認できるのであれば、確認しながら掛けるといいと思います。なるべく両サイドの分布が少なくなるようにする方がいい感じになります。

f:id:hiyokosabrey:20171205213144p:plain

仕上げにトーンカーブで(0,0,0)と(255,255,255)を無くします。

試せばわかるのですが、無くしておかないと、マスクで使う際に完全な白と黒にならないからです。

f:id:hiyokosabrey:20171205223420p:plain

 このトーンカーブは調整レイヤーで作業すると使い回しができて便利です。

 

 

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

 Grayscale で sRGB を使わない設定にします。

最後に大事なのが、Filter設定。これを、Nearest にしておきます。

f:id:hiyokosabrey:20171205224059p:plain

 

あとは適当な絵を2枚用意してマテリアルを作ります。

f:id:hiyokosabrey:20171205231157p:plain

 ValueStep ノードはPhotoshopでいうところの『2階調化』っていうやつです。

Gradientのピンにグレイスケールの絵を流して、Mask Offset Value のピンで閾値を加減します。

 

これを、Widgetで確認します。

このマテリアルをキャンバスのImageパーツにセットします。

グラフに置いてある Event Pre Construct で ダイナミックマテリアル化しておきます。

f:id:hiyokosabrey:20171205232009p:plain

 

アニメーションのために、隠しパーツをキャンバスに一つ置いておきます。

 この辺の操作は過去記事でもやってたので一応貼っておきます。

limesode.hatenablog.com

このパーツの Pivot あたりにアニメーションを付けます。値は 1.0 → 0.0  になるようにします。

もちろん非表示なので、 Visibility は Collapse にしておきます。

全開の記事では Hidden にしていましたけど、Hidden よりも Collapse の方が処理がかからないそうです。

 

あとはこの隠しパーツ(今回 Invisibleと名付けました)の値を拾って、ダイナミックマテリアルに渡すようにしておいて、

f:id:hiyokosabrey:20171206033128p:plain

アニメーションを再生すればOK。

再生用のイベントを用意しました。

f:id:hiyokosabrey:20171206034225p:plain

 

レベルブループリントで確認用の CreateWidget → Add to Viewport をつなぎます。

そして、Input ~ で再生用のイベントを呼び出せば簡単に確認できます。

f:id:hiyokosabrey:20171206035050p:plain

繰り返し確認するために、リセットするイベントを用意しました。

f:id:hiyokosabrey:20171206035318p:plain

 

では再生してみると・・・

f:id:hiyokosabrey:20171206041024g:plain

(実際はもっと速いのですがGIFの再生速度が限界っぽい)

 

再生速度はタイムラインで調整できます。

ポストプロセスマテリアルに応用すると、画面遷移として使えそうです。

マスクテクスチャをグレイスケールで作れば、StepValue で段階的なアニメーション表現ができるので楽しいです。

今回はデジタルノイズっぽくランダムにしたかったのと、テクスチャを安く作りたかったので、普段あんまり使わないNearestを使ってみました。

 

こんなやつだと

f:id:hiyokosabrey:20171206044958p:plain  64x64px をマテリアルでタイリングしました。

f:id:hiyokosabrey:20171206045323j:plain

同じサイズで円形のグラデーションにすると

f:id:hiyokosabrey:20171206045926p:plain

f:id:hiyokosabrey:20171206045948j:plain

 

階調を反転すると、また違った見え方になります。

 

 

ではでは今回はこの辺で。

ステキな画像切り替えライフを!

UMGの移動アニメーションを作る場合

UMGで移動アニメーションを作る場合、PositionTranslation の2種類があって、表示された見た目には違いがないように感じますが、それぞれ仕様が違うので私は使い分けて使っています。

今回はその使い分けについての私なりの解釈をぐだーと書いてみます。

 

下図は、UMGのキャンバスに置いたImageパーツのDetails(詳細)タブ。

f:id:hiyokosabrey:20171103113340j:plain

まず先に書いてしまうと、

  • Position は レイアウト用
  • Translation はアニメーション用

として捉えています。

実際に使ってみると判るのですが、ポイントは座標の扱い方が違うという点です。

Position は Anchor を基準としたキャンバスパネル内の絶対位置である「居場所」を指定します。一方 Translation は今いる場所からの プラスマイナスした位置という「移動量」を指定します。コトバの意味としても、辞書を見ると translate には「場所」をイメージさせるような訳がなく「翻訳」の他に「変形」という和訳がありました。

カテゴリも Render Transform ですしね。

なので、覚え方としては、

  • Position で指定した場所から Translation で指定した分だけ変形

となります。

「移動」と書かずにあえて「変形」と書いたのは、UMGでは移動も変形として扱っているからです。

3Dモデルで考えると解りやすいのですが、まずモデルには中心(Center)があって、そこから離れた位置に各頂点(Vertex)があります。この各頂点はモデルの中心からの相対位置でデータ化されています。Transform は形状を変形させることになり、変形することは頂点が移動することを意味します。例として頂点4個の四角いメッシュでイメージ図を作ってみました。

f:id:hiyokosabrey:20171103144901p:plain

f:id:hiyokosabrey:20171103144913p:plain

 UMGやFlashのような2DベースのGUI制作に慣れ親しんでいると、この「頂点」があるというイメージは感覚的に身に付けるのは難しいかもしれませんね。

 

ちなみに

キャンバス内でレイアウトを触っていると、値が変化するのは、Position の方で、Translation は、0.0 のままです。

 

 

ブループリントで位置を触る場合

位置を変えることができるノードは2つあります。

Position の方は Canvas Slot 型に キャストしてやる必要があります。

 

f:id:hiyokosabrey:20171103115727p:plain

Image_22 というのはUMGでテキトーに置いたImageパーツです。

 

変数には Canvas Panel Slot型というのがあるので、ブループリント内で繰り返しPosition を触る場合は、変数化しておくと便利です。

f:id:hiyokosabrey:20171103142255p:plain

 

で、結局のところ・・・

移動アニメーションは基本的に Translation で行うと扱いがラクになります。

UMGのキャンバスでのレイアウトの変更や調整がやりやすいからです。

 

例えばフレームインしてくるアニメーションの場合、まず最終表示位置にパーツを並べて位置を決定します。そのあとで、Translation でそこから表示開始位置まで移動するのをアニメーションキーで登録します。この時の値は、いくらか離れた位置を開始位置にして、終了位置は必ず 0.0 になります。開始位置のキーは、単に移動量を表わすことになりとてもシンプルです。

 

後で、レイアウト上の問題が発生してこの最終表示位置をキャンバス内で修正したとしても、調整レベルであればアニメーションキーの修正は必要ありません。これが結構メリットになります。

 

座標の扱いについてまとめると

  • Position は キャンバスに対しての 絶対座標
  • Translation相対座標 または Position からの オフセット位置

ということになります。

 

UMGのAnimationでは Translation で動きをつけ、ブループリント では Position を使って配置する、といった使い方が便利でよく使う手です。

 

 

 今回は以上です

 Position と Translation の使い分けで、迷っておられる方があれば、ぜひ参考になればうれしいです。

 

ではでは ステキな移動アニメーションライフを!

 

 

UMGのテキストを動かしてみる

UMGでテキストを表示します。キレイにアウトラインフォントが表示されます。

うん。

・・・・。

そう、ちょっと刺激が足りないなと、気づいたのです。

このままで終わっていいのか?テキストブロック!

お前の人生、ただ指示された通りの文字を並べるだけでいいのかよ!

と、中学校の文化祭に行って観劇してたら急にそんな気分になったのでした。

で、

テキストの文字を1文字ずつアニメーションさせてみようと思って遊んでみました。

 

テキトーにWidgetブループリントを用意します。

さっそくキャンバスに、Horizontal Box をひとつ。is Variable のチェックを忘れずに。

f:id:hiyokosabrey:20171020213815p:plain

あと、Size to Content にもチェックを付けます。

で、

ブループリント。

 

まず変数を3つ新しく用意します。

f:id:hiyokosabrey:20171020213710p:plain

上から、

Boolean型の変数は、準備できるまで、 Event Tickに我慢させるためのフラグ。

TextBlock型の配列変数は、文字をバラバラに管理するため。

Float型の変数は、サインカーブのための角度を保持するため。

 

変数が用意できたら、続けて関数を一つ。

関数にも、ローカル変数を3つ。これは関数内だけで利用される変数。

f:id:hiyokosabrey:20171020221553p:plain

上から、

String型の変数は、パラメータとして受け取った文字列を保持しておくため。

Slate Font Info型の変数は、フォントの設定を保持させておくため。

Integer型の変数は、受け取った文字列の長さを保持しておくため。

 

ちょっと画像が大きくなったので、左右で2枚になりました。

f:id:hiyokosabrey:20171020222152p:plain

文字列の長さを、 Lengthノードで調べると、単純に文字の数を調べてくれます。

例えば、"0123456789" のように数字が並んでいる場合、文字の数は10個です。

ForLoop ノードでは、繰り返しの回数を指定する場合に、Index番号という数値で管理します。なので、例えば回数を10にしたい場合、開始 Indexが 0 、終了 Index が 9 となります。

開始 Indexが 5 、 終了 Index が 14 の場合でも、ループ回数に変わりはないのです。

じゃあ、1から始めりゃいいじゃん、ってなるかと思うのですが、最近「ゼロから始める○○」が人気のヒケツ(?)っぽいので、まぁそんな感じです。(実際は座標なんかを計算したり配列を扱うときにゼロから始まっていた方が都合がいい場合が多いのです)

 

なので、ForLoopの繰り返し処理では、文字列の長さを、Last Indexとして使うためには 予め ー1しています。

 

変数の値を参照しにいくたびに 毎回 -1 の計算が入ってしまうのを避けるために、下のようにしています。

f:id:hiyokosabrey:20171020223655p:plain

ForLoopの中を見てみると、First Index は回数をカウントするためにローカル変数で管理されていますが、 Last Index の方は、毎回 つながったピンの値を参照します。

下のようにつないでしまうと、Last Indexピンが値を受け取ろうとするときに、-1の計算が入ってしまいます。

f:id:hiyokosabrey:20171020223825p:plain

この程度たかが知れてますが、普段から意識してないと「チリツモ」になりやすいので、エンジニアと良好な関係を築くために、UI紳士としては意識しないわけにはいかないと思うのです。

はい、流れを戻して続きを。

f:id:hiyokosabrey:20171020225505p:plain

左端のノードは、Construct Object from Class という名のノードです。

↓取り出した直後の状態。

f:id:hiyokosabrey:20171020225745p:plain

Classをセットすると、NONEの部分の表記が変わります。今回はテキストブロックなので、Text をチョイスします。

 

ローカル変数 TempFontの中身は、Details (詳細)タブで設定します。今回はこんな感じ。

f:id:hiyokosabrey:20171020230224p:plain

 

この関数では、テキストブロックをブループリントで生成しています。

そしていつもなら、クリックとキーボードで設定していた内容も、変数と専用のノードを組み合わせて設定しています。一文字づつ処理して、Horizontal Box に並べていくのです。

ひととおり並べ終わったら、ループ処理のあとに、ブーリアン型の変数に True をセットします。

これで関数は完成。

 

つぎにアニメーションの部分。Event Tick を利用します。

関数が呼ばれると、文字列がバラバラになって並べられて、最後に ブーリアン型の変数に True が入ってようやく、このEvent Tick が最後まで稼働します。

f:id:hiyokosabrey:20171020230926p:plain

Event Tickは、 このWidgetブループリントが Viewport に置かれたらすぐに動き出します。関数が呼ばれる前に動き出すとエラーが出るので、必要な処理が終わるまでは、Branchノードでブロックしています。

 %ノードは、 値がずぅーっと加算され続けるのを防ぐためと、円の1周分の角度は360度だからです。

角度から、三角関数を使って 値を計算します。その担当をマクロにしました。

f:id:hiyokosabrey:20171020233958p:plain

Period は カーブの周期(的なもの)、Radius は 半径 です。

中身はこうなってます。

f:id:hiyokosabrey:20171020234221p:plain

三角関数の角度Θ(シータ)にあたる部分は、「ラジアン」(Radians)が基本かと思いますが、ブループリントでは、0°から360°の「角度」(Degrees)で扱うノードも用意されています。

f:id:hiyokosabrey:20171020234801p:plain

マクロでは角度 Degrees の方を使用しています。

 

これで準備はできました。

あとは関数を呼び出して文字列を渡すだけです。

とりあえず確認のために、Event Construct につなぎます。

f:id:hiyokosabrey:20171020235150p:plain

 

これで Widgetは完成です。

 

 

あとはレベルブループリントにて、Viewportに追加するだけです。

f:id:hiyokosabrey:20171020235427p:plain

 

再生してみましょう。

 f:id:hiyokosabrey:20171021000449g:plain

 Screen to GIF というアプリを使ってみました。

ちょっとひっかかるときがあるけど、い感じに撮れてます。

サインカーブを、Y座標にするこんな風に上下にユラユラします。

 

マクロのパラメータをいろいろいじると揺れ具合が調整できます。

Period を大きな値にすると、カーブが細かくなってジグザグします。

Radiusの値を大きくすると上下の揺れ幅が大きくなります。

 

この値を、Shear や Angle にセットしても面白い動きになります。

f:id:hiyokosabrey:20171021001200p:plain

 

 Angleの場合。

f:id:hiyokosabrey:20171021001729p:plain

できたのが

f:id:hiyokosabrey:20171021001745g:plain

 

Shearの場合。

f:id:hiyokosabrey:20171021002328p:plain

動きは

f:id:hiyokosabrey:20171021002352g:plain

ちょっと酔いそう。

 

サインカーブは、プラスとマイナスの値を行ったり来たりするので、どちらか一方だけにするとバウンドするような動きになります。

f:id:hiyokosabrey:20171021003928p:plain

 すると、

f:id:hiyokosabrey:20171021020110g:plain

他にもカラーを変えてみたりもできます。

 

ロード画面くらいしか使える場所は無さそうですが、ちょっとは刺激的になった気がします。なかなか楽しいですねUE。

 

ではでは 今回はこの辺で。