みつまめ杏仁

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

テキスト入力を試してみる

 最近帰りが遅くて、駅から家までの経路に田んぼがあるんですが、毎晩カエルの大合唱を聞きながら歩いて帰宅しています。 月の映る水面をチラ見しながら歩きつつ、ダンジョンメーカーに勤しんでる今日この頃です。はい、歩きスマホはダメですよ~。

 さてさて、訳あってUMGのテキスト入力を試すことにしました。公式のWebドキュメントを見ていると、何やらいくつか種類がある様子。とりあえず最近のエンジンのバージョンで見てみるとこんな感じ。特に変わった様子はない。

f:id:hiyokosabrey:20190627001306p:plain

 公式ではPrimitiveの中にカテゴライズされた画像が貼ってある。いつのVerだろうか。

 

 

見た目

とりあえず、Text で Box なやつをピックアップして並べてみた。

f:id:hiyokosabrey:20190627223539p:plain

 一見すると背景有り無しと、改行ありの複数行タイプか、改行なしの1行のみのタイプ。名前的に EditableText TextBox この2タイプに分けられている理由が分かれば話が早いんだけど、公式ではこれといって言及されてないっぽい。公式以外で触れている情報が少ない。まぁだいたい理由は想像つくけど。

 

 実際に表示してみて試してみると、ほとんど差が分からない。大きな差があるのは、Style という設定項目を持っている TextBox(Multi-Line) 。こいつはスクロールバーも持っている。それ以外の3つは、いつもお世話になっているTextBlock と同じような Appearance を備える程度。

f:id:hiyokosabrey:20190628180632p:plain

f:id:hiyokosabrey:20190628180642p:plain

f:id:hiyokosabrey:20190628180650p:plain

f:id:hiyokosabrey:20190628180659p:plain

 

 機能要件の差とコンポーネントとして作られ実装された時期によるものだと思うけど、さすがにこれはちょっと躊躇う。TextBox(Multi-Line)だけは、Appearance の項目スッキリしていて、見た目の調整は Style という設定カテゴリにまとめてある。

 

f:id:hiyokosabrey:20190628181611p:plain

 

 自分の作りたい見た目が実現可能かどうか、実際に試してみながら判断するしかなさそう。

 

ちなみに、

キャンバスに置くと、is Variable に最初からチェックが付いてて、どちらもブループリントで触れるようになるんだけど、デフォルトの名前とアイコンがこれ↓

 

f:id:hiyokosabrey:20190628213137p:plain

ほとんど同じ。Box 付きは 実線で、 Box無しは 破線のアイコン。

 

 

イベント

 用意されているバインドできるイベントは4種類とも  OnTextChanged と OnTextCommitted の2つ。

 

f:id:hiyokosabrey:20190628174735p:plain

 

 全部置いてみたらこうなった↓

f:id:hiyokosabrey:20190628214027p:plain

 

OnTextChanged~ は内容が変更されるたびに呼ばれるイベント。

OnTextCommitted~ は内容が確定(編集終了という意味合いだと思う)した際に呼ばれるイベント。このボタンからイベントを作って試してみたら、このWidgetのフォーカスが外れた際に、確定したと認識されるらしい。

 

 変数化したオブジェクトから、 イベントを検索してみても専用のやつは上の2種類だけみたい。

Widget Event というカテゴリにある。

f:id:hiyokosabrey:20190628215206p:plain

 

 ところがTextBox だけは違ってて、Text Box というカテゴリが用意されてる。さすがCommonカテゴリに分類されるだけのことはあるとうことか・・・

f:id:hiyokosabrey:20190628215047p:plain

 

 ブループリントからも見た目をいじることができて、Get Style ノードが用意されているけれど、EditableText (Multi-Line) だけは なぜか、 Get Widget Style という名前のノードで別のカテゴリに分類されている。グラフに取り出してみるとこの通り。

f:id:hiyokosabrey:20190628223031p:plain

 こうやって比較してみると、ややこしい事この上ない。まさに 混ぜるなキケン!

 というやつか。

 

 ここまできて、今更ながら思ってたより深い沼だったことが判ってしまった。そっ閉じしてあとはEpicの猫のひとかhistoria様のブログに期待を寄せる方がいいかもしれない。などと弱音を吐いてみる。

 とりあえず、このまま比較していくと、全て検証を終えた時には夏休みも過ぎ2学期が始まってしまっているかもしれないので、どれかに決めて次に進もう。

 

 改行処理を試したいので複数行が扱える EditableText(Multi-Line) に決める。

 

 

 いじる

 背景があった方が大きさが分かりやすいので、テクスチャを用意。

f:id:hiyokosabrey:20190629101837p:plain

この64x64のテクスチャを Image にセットして、Box で描画する。

f:id:hiyokosabrey:20190629103025p:plain

 

とりあえず必要そうなパーツを置いてそれっぽくする。

f:id:hiyokosabrey:20190629102835p:plain

ヒエラルキーは ↓のような状態。

 f:id:hiyokosabrey:20190629103226p:plain

 

 今回、EditableText(Multi-Line) が主人公なのでサイズが固定。これに合わせて他のパーツを調整することになるので、背景(Image)のサイズをEditableTextと一緒にしておき、マージン設定で内側に余白をつくり、見た目の枠と距離をとるようにしています。

f:id:hiyokosabrey:20190629105047p:plain

 EditableTextのサイズが変わっても、サイズをコピペするだけなので、頭使わなくていいというメリットがあります。この辺は好みの分かれるところかもしれないですね。

 

 改行(Wrapping)の設定もチェック。

 Default Wrapping だと、単語と単語の区切りで改行してくれるけど、日本語のように半角のスペースを入れない文字列だと、意図的に改行しない限り、ず~と右にはみ出してしまう。なので、 Allow Per Character Wrapping に変更します。

 f:id:hiyokosabrey:20190630000030p:plain

 

 ボタンをクリックしたときに実行されるOnClickedイベントをバインド。PrintString につないで確認してみる。

f:id:hiyokosabrey:20190629144331p:plain

 

f:id:hiyokosabrey:20190629145601g:plain

 

 改行文字を置換できるか実験。Get Text ノードから PrintStringノードまでを関数にする。

f:id:hiyokosabrey:20190629152105p:plain

 

 文字列をゴニョゴニョするには、Text型を 一旦 String型にしてやる必要がある。関数にすると、ローカル変数が使えるから一時的にStringの処理をするにはうってつけ。

 関数の中身はこんな感じ。TempStr というのがローカル変数。

f:id:hiyokosabrey:20190629152521p:plain

 Replace ノードは From に置換対象の文字列を入れて、To に 入れ替える文字列を入れて使う。Shift キーを押しながら、Enter キーを押すと、改行文字が入力できるので、From に改行文字を、 To に  <> を入れて試してみる。

 

f:id:hiyokosabrey:20190629153145p:plain

 

 無事置換できた。

 

 次は、行数に制限をかける方法を考えたい。

f:id:hiyokosabrey:20190629154714p:plain

 

 それっぽいノードや設定項目はなさそう。

 とりあえずWidget Reflector で見てみると、

f:id:hiyokosabrey:20190629172843p:plain

 Desired Size が入力した文字によって変動しているのが判った。

 内容が変更されると呼ばれるイベントでGet Desired Size ノードで調べて表示させてみる。

f:id:hiyokosabrey:20190629173223p:plain

 1行・・・52.590

 2行・・・89.181 (+36.591)

 3行・・・125.771 (+36.59)

 4行・・・162.362 (+36.591)

 5行・・・198.952 (+36.59)

 6行・・・235.543 (+36.591)

 

いったん一つ前の内容をキャッシュしておいて、オーバーしたら、強制的にキャッシュで上書きするというのを試してみる。

f:id:hiyokosabrey:20190629180422p:plain

  どうやらDesired Size の値が遅れていることが判明。内容が変化したタイミングでは、Desired Size が更新されていない様子。Reflectorではきっちり取れてたっぽいのだけど。

 

ということで Force Layout Prepass を入れてみたらうまくいった。

f:id:hiyokosabrey:20190629181235p:plain

 

 改行文字を置換する関数を少し整えて、結果をReturnValueにして外に出すようにする。ついでに、キャッシュ用の変数も更新。関数名をFormatTextToStringに変更。

f:id:hiyokosabrey:20190629201931p:plain

 

 ちょっとした演出を作ってみます。

 

まずは、文字を削る関数を用意します。

f:id:hiyokosabrey:20190629203733p:plain

ここでもEditableTextの内容を一旦ローカル変数に入れて、 Right Chop というノードで一文字削って また元に戻しています。

 

この関数を動かすために、カスタムイベントを新しく作ります。

f:id:hiyokosabrey:20190629204050p:plain

結果を見て、引き続き実行するかしないかを分岐します。文字の数だけこのカスタムイベントが実行されます。

 

あとは、送るボタンを押した時に、このカスタムイベントを呼べばいいだけ。

f:id:hiyokosabrey:20190629204310p:plain

 

Playしてみると。

f:id:hiyokosabrey:20190629205131g:plain

送ってる感が出てる気がする。

 

ひとまずこんなとこかな。

 

 

おまけ

ビヘイビアの設定をちょっとだけ確認してみた。

 

■ Select All Text when Focused   初期値:false

これを有効にすると、フォーカスした際に、テキストが全選択された状態になる。

コピペさせたい時に使えそう。

 

■ Clear Text Selection on Focus Loss  初期値:true

選択中の文字列がハイライトされた状態を維持するかどうか。デフォルトだと、フォーカスが他に移った時点でハイライト(Selection)がクリアされる。

 

■ Revert Text on Escape  初期値:false

入力中のテキストを一つ前の状態に戻すかどうか。フォーカスアウトした際にテキストの内容が確定してどこかしらに保存されるようで、内容を書き換えて ESCキーを押すと、フォーカスアウトした時点に戻る。書きかけでも安心。

 

■ Clear Keyboard Focus on Commite  初期値:true

キーボードでのフォーカス遷移に関係してそうだけど、うまく検証できなかった

 

■ Allow Context Menu  初期値:true

 いわゆる右クリックメニュー。有効にするかしないか。

f:id:hiyokosabrey:20190629224351p:plain

 

そういえば、 Appearance の設定で気になるのがあって、まだ使い方が分かってないんだけど、あれは リッチテキスト用かな?また機会があれば触ってみたいと思います。

 

 

最後に

今回の文字入力用Widgetについてあまり記事が上がっていない件で、思いつく範囲で少し触れてみたいと思います。

使い方はそれほど難しいものでもない。

というのが、あえて記事に取り上げる意欲が湧かない要因だと思いますが、ゲームでユーザーのテキスト入力を扱うということは、とてもたくさんのリスクを作り手側が負うことになるので、慎重にならざるを得ないのが実情で、これによって扱わない開発者も多いのでは、というのも結構大きな要因かと思います。

まずこのリスクをいくつか挙げておきます。

 

 アジア圏の文字種の多さ。これは多言語対応する場合はフォントの選択肢が現状ほぼありません。表示できない文字が出てくる。

 フォントの契約によっては、ユーザーが自由に文字組を編集できるということがライセンス許諾外になることが多く、その場合追加のライセンス料が発生することがある。

 差別や性的、侮辱的、ドラッグ絡みなどのNGワードの置き換え処理が大変。オンラインだと多言語での対応になるので。日々ネットスラングが生まれる現状でセンシティブな内容にどこまでシステムがフォローできるかは頭の痛い問題。置き換えをあきらめた場合は、ダイアログウィンドウで事前に告知したり、不快な文章を発信しているユーザーを報告したりキックできる仕組みが必須になります。

 オンラインの場合、UGC(UserGeneratedContents)になりうるので、これもゲームの場合、CEROESRBなど、レーティングが上がることになります。

 

 ちょっと前に流行ったのは自由文ではなく、定型文の組みあわせによる文字列生成。

これはフォントの問題は解決できるし、事前に翻訳できるので多言語対応しやすい。

最近ではスタンプもよく見かけます。

 

 ユーザーが文字入力できるというのはそれなりに覚悟がいるので、実装経験が少ないということだろうと、勝手に推測しています。

 

 

ではでは

今回はこの辺で

ステキな文字入力ライフを!