読者です 読者をやめる 読者になる 読者になる

たいちょーの雑記

ぼくが3日に一度くらい雑記をかくところ

UnityでInputFieldを使わずに文字列を受け取る

C# Unity

掃除するときは気を付けろ

奴は大事なものを捨てていっちまったんだ

InputFieldでいいんじゃないのか?

最近せっせこ作っている作品では、キーボードからの文字列入力と同じ場所に出力が必要だったのでUnityがuGUIで提供しているInputFieldを使おうと思いました。
docs.unity3d.com

ふつーに文字列を受け取るところがあって、背景やフォントも変えられるふつーの入力フォームです。イベントの通知もできます。
Textを子に持っていてInputField.textに書き込んでやれば出力もできると踏んでました。
NoIF1

しかし問題点が一つありました。Enterを押すともう一度Enterを押さないと入力待ち状態にならない点です。
ぼくが欲しかったのは コマンドラインのような入出力環境 だったのです。
NoIF2
こういうの

Enterを押したらC#に入力文字列を送信して、また次の入力待ちしてほしいのです。
InputFieldのリファレンスを読んでみましたが、それっぽいプロパティは見つかりませんでした。
唯一Interactableというプロパティがそれっぽかったのですが、どちらかというとenabledに近い動作だったので期待した動作を実現できませんでした。

つくった

こういう痒いところに手が届かないときはワクワクして自前で用意していきます。
使うのは同じuGUIのTextです。
docs.unity3d.com
NoIF3
見づらいな

入力を受け取るソースはこちら

this.UpdateAsObservable().Subscribe(_ =>
{
    foreach (char item in Input.inputString) {
        if (item == '\b' && user_inputString.Length > 0) {
            user_inputString = user_inputString.Substring(0, user_inputString.Length - 1);
        } else if (item == '\r' || item == '\n') {
            user_inputString = "";
        } else {
            user_inputString += item;
        }
    }
    updateCommandLine();
});

Updateの代わりにUniRxを使っています。理由は特にないですけど
InputクラスのinputStringプロパティからそのフレーム中に入力された文字列を受け取って1字ずつ解読していきます。
もし\b(backspace)だったらSubstringで一字消し、\n(Enter)であれば文字列をクリアします。それ以外なら入力文字列として追加していきます。

こんなんでうまくいくんかいって思いながら書いてたんですが
NoIF4

ありえんぐらいうまくいった

ひとつ問題点があるとすれば日本語はEnterで確定するまで表示されないところですね。まあ使う予定がないのでいいですが

いつもこれくらいトントン進めばいいんですけどね。