みつまめ杏仁

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

文字がシャッフルしながら出てきてランダムに消えていくやつについてのメモ

さすがに涼しいと言ってられないほどの気温になってきました。ほんの数日でしたが大好きな稲刈り後の田んぼの匂いと金木犀の香りで秋の深まりを実感している今日この頃です。

 さてさて ちょっと間があいてしまいましたが、先日Twitteにあげたテキストエフェクトについて書こうと思います。

 

 

今回のはブループリントは載せずに、どういった構造にしたかをメモします。

多分もっといい方法がありそうなのと、実際の需要としてはニッチすぎるので、BPの組み方やら、UMGの作りはまず参考にはならないだろうという想定です。

 

ということで、まずはシャッフルしながら文字列がでてくるやつ

 

初めに考えたこと

1文字分だけ表示するWidgetを作ってそこでランダム処理をさせる方法。

ある文字列をバラして、1文字づつをWidgetにシャッフル時間と共に初期値として渡して並べるだけというラクな発想。

f:id:hiyokosabrey:20201029230537p:plain
フォントの選択肢が多いのと、放置プレイできて便利なんだけど、文字数が多くなると、それだけWidgetの生成と消滅が発生するので、ちょっと負荷が心配になるので却下。あとレイアウトも考慮すると管理するWidgetの階層が増えそう。

 

そこで、TextBlock ひとつのままでシャッフルできないか考えてみた。

f:id:hiyokosabrey:20201029230556p:plain

要するに文字列の段階でいかにしてうまくシャッフルの文字列を作るか。

さらに、

  • シャッフルが始まって全部が一斉に止まるのはやりたくない
  • 少しずづ確定させたい
  • 端からではなくランダムに

というのをハードルとして課すことにした。

 

 

あらかじめランダムな文字列を作ってしまえばいいのでは?

文字列を受け取ったら、その文字数分のランダム文字列を先に作り置きして、あとは順番に取り出して表示するという方法を思いついた。なんかよさそう気がする。問題なのは、どうやって少しづつ確定させるか。

年々しぼんでいく脳みそで頑張ってみた結果、配列を使うとうまくいきそうな気配を感じたので試してみた。

まず文字列を配列にバラせるかどうか ノードを漁ってみるといいノード発見。

f:id:hiyokosabrey:20201029232144p:plain

 

String型の配列を用意して、文字数分の要素を確保。

 

f:id:hiyokosabrey:20201030002021p:plain


ここに、ランダムな文字をランダムな文字数ぶん入れて、最後に表示する確定文字で埋める。

配列の各要素に入れる最大文字数は演出時間で調整するとして全部一律。

最大文字を14とした場合。

 

f:id:hiyokosabrey:20201031155422p:plain


紫色の文字がランダム文字、青色の文字が確定文字。

ヨコが配列の要素、タテが要素内に並べた文字列。

あとは表示する際、先頭から順番に取り出して、くっつけて表示する。

f:id:hiyokosabrey:20201031155403g:plain

 

表示してみるとこんな感じ

f:id:hiyokosabrey:20201031161322g:plain

思ってた感じにできた。

 

ランダムと言っても、ある程度幅の調整は必要。

f:id:hiyokosabrey:20201031161617p:plain

ランダム文字の生成は、固定の文字列から一文字を抜き出す方式。

f:id:hiyokosabrey:20201031162554p:plain



 

消えるときもランダムで虫食いっぽく消したい

ランダムの欠点というか残念なところは、同じ数を引いてしまうことがあるとこ。

ランダムに位置を決めたら文字が空白かどうかチェックして、空白じゃなければ消す。空白だったら、再びランダム位置決め・・・ これだと終盤空白だらけになった時、空白じゃない文字を引く確率が下がってしまい、最後まで消えきる時間が不安定になってしまう。

そして思いついた方法が2つ。

一つは、表示している文字がアルファベットと数字だけなので、順番に検索をかけてヒットしたら消すことにすると、確実に一定の時間内ですべて消える。

確実に消えるけど、”WWW”みたいな文字列があると、一斉に消えてしまうのと、法則性が見えてしまいそうなのが無粋かな。

 

でもう一つの方法が、文字列の中で消す順番をランダムにする方法。

順番を決定するための配列を増やすことで対応できそうということで試してみることに。

まず表示している文字列と同じ数の要素を持った配列を用意。

そこへ、0~ 順番に数値を入れていって、最後にシャッフル。

 

f:id:hiyokosabrey:20201031170149p:plain

 

配列の要素をシャッフルしてくれるのがこのノード

f:id:hiyokosabrey:20201031170131p:plain

 

この配列の要素を順番に取り出しながら、表示している文字列を空白に置き換えていく。

文字列操作のノードを駆使してなんとかこんな感じでできた。

f:id:hiyokosabrey:20201031170643p:plain

Leftノードは、文字列の左から指定文字数ぶんをゲット、同様に Rightノードは文字列の右から指定文字数ぶんをゲット。

該当する場所の文字をよけて、切り出すイメージ。

f:id:hiyokosabrey:20201031172632p:plain

 

これで、配列の要素数ぶん(=文字数)この処理を繰り返せば確実に毎ターン一文字ずつ消えていくという寸法。

 

f:id:hiyokosabrey:20201031173653g:plain

 

これで出来上がり。

 

↓これは、Twitterに上げたGIFで 30fpsで撮ったもの。

f:id:hiyokosabrey:20201031173923g:plain

 

一応満足いく形にできた。

 

でもしばらく眺めているうちに 確定したタイミングでもう少しメリハリが欲しいかも、と思ってカラーで変化をつけてみた。

 

f:id:hiyokosabrey:20201031190654g:plain

ビビリだけUMGのタイムラインで、出現時と消滅時は、Lerpノード を使ってるので、文字数によって時間の長さが変わっても大丈夫なつくり。

 

 

とりあえずこれで良しとしよう。

ランダムとうまく付き合うのは、なかなか骨が折れるというか、神経を使う感じですが、UI表示でランダムを使えると楽しいので、頑張ってしまいます。

プログラマーに指定書で細かく書いて渋い顔されて、いざ画面に表示されてからさらに微調整するといった面倒に突き合わせて申し訳ない気持ちになったな時代は遥か彼方。

いい時代になったもんです。

もっと効率のいいやり方とか、賢いやり方があると思うので、共有してくださる方が現れるのを期待して、この記事を書いています。

 

映画の冒頭やアニメのオープニング、ボカロのMVとかで面白いテキスト表現に出会うとうれしくなります。と同時に先を越されたような口惜しさも味わうことになります。

ゲームは動画ではなくリアルタイムで描画するので、インタラクティブな見せ方ができるのが魅力の一つ。映像作品を参考にしたりUE4でいろいろ実験して、テキスト表現のネタを引き出しにしまいつつ日々精進してまいりましょう。

 

ではでは

ステキ な テキストエフェクトライフを!