InputFieldに文字を入力して、それを受け取ってどっかに表示したい。もしくは、受け取ったものを何かしらに使いたいなんていうことがあるかもしれない。これが割とややこしいので、自分なりに調べてみた。
今回はとりあえず、inputFieldに入力された文字を別の場所に出力する方法を見ていく。
InputFieldと出力用のTextを用意する
まずは最初に、文字を入力する用のInputFieldと出力用のTextをHierarchy上に用意していこう。適当なプロジェクトを作成したら、Hierarchy左上のUIボタンをクリックして、inputFieldをクリック。同じ方法でTextも用意しておこう。
作成したら、自分の見やすいように場所などを移動しておこう。
Hierarchy上のTextの名前をわかりやすいようにDisplayTextと変更しておく。
スクリプトを用意する
次はスクリプトを作成する。作ったスクリプトは正直どこにアタッチしてもよいと思うが、今回はInputFieldにくっつけようと思うので、InputFieldManagerとでもしておこう。
作成したら、Hierarchy上のInputFieldにアタッチしておこう。D & D(ドラッグアンドドロップ)でもAdd Componentでも好きな方法で。
スクリプトに書き込みをしていく
InputFieldManagerを作成してアタッチしたので、今度はこのスクリプトに以下のように記述していく。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class InputFieldManager : MonoBehaviour
{
//出力用のテキスト
public Text displayText;
//inputFieldのOnEndEditに設定する用の関数
public void OnEndEdit()
{
//InputFieldコンポーネントのtextを変数に代入
string inputFieldText = GetComponent<InputField>().text;
//出力用のテキストに代入
displayText.text = inputFieldText;
}
}
忘れちゃならないのが、UIをスクリプト上で使いたい場合にはUnityEngine.UI
を書くこと。
ではコードを一応上から見ていこう。
public Text displayText;
の部分。これは箱をイメージしてほしい。型がTextなので、この箱にはTextクラスしか入れられない。
public Text displayText;
の部分に、「入力内容を反映させたいText」をインスペクタ上から入れる。そして、使えるようにしていく。(今回だったら、DisplayText)。FindやTagで取得する方法などもあるが、手っ取り早いのでアウトレット接続にする。
次のpublic void OnEndEdit()
これは関数だ。この部分が今回の目的である「InputFieldで入力した内容を出力する」という処理の部分だ。
関数の中のstring inputFieldText = GetComponent<InputField>().text;
の部分。ここでInputFieldコンポーネントのtextを取得しているぞ。コンポーネントはUnityの重要な概念なので、わからない人はググろう。
最後のdisplayText.text = inputFieldText;
で取得してきたinputFieldTextを出力用のテキストに代入している。
スクリプトが書けたら、インスペクタ上で設定をしていこう。
変数displayTextにアウトレット接続をする
上で用意した変数、public Text displayText
部分にHierarchyのDisplayTextを持っていく。pubicをつけることで、inspector上から設定できるようになる。
InputFieldコンポーネントのOnEndEditに関数を設定する
次は関数の設定だ。スクリプトの中でOnEndEdit
関数を作成した。関数は作っただけじゃ勿論発動しない。どこかで、これを呼んであげないとダメだ。
これをどこで呼ぶかだが、InputFieldオブジェクトをクリックしたら、インスペクタ上から、InputFieldコンポーネントを確認してみてほしい。
下にスクロールすると、OnValueChanged
とOnEndEdit
があると思う。
OnValueChanged
はInputFieldに文字を打ち込んでいる最中に呼ばれる関数。
OnEndEdit
はInputFieldからフォーカスが外れた時に呼ばれる関数だ。
最初はOnEndEdit
の方にOnEndEdit関数をくっつけていこう。関数名は、わかりやすいように名前をつけただけで、OnEndEditっていう名前じゃなくてももちろん大丈夫だ。
以下のように関数を設定していこう。
On End Edit の+ボタンをクリック
クリックしたら、Noneになってるからここで使いたい関数を設定する。使いたいOnEndEdit関数はどこにアタッチされているかというと、InputFieldオブジェクトにアタッチされている。なので、NoneのとこにInputFieldオブジェクトをHierarchyからD&Dしよう。
そしたら、No Functionの下矢印をクリックして、OnEndEdit関数を読んでこよう。
これで関数も設定完了だ。
ポイントは「使いたい関数が書かれているスクリプトがアタッチされているオブジェクトを設定する」ことだ。
プレイして確かめてみる(OnEndEdit)
ここまで出来たら、後はプレイボタンを押して確かめてみる。
アルファベットを入力してEnterを押して成功。
日本語を入力してEnterを押して成功、、あれ?文字が消える。
なぜだか、日本語の場合Enter押したら文字が消えてしまう。
Enterではなく、クリックを外で行ったらうまくいった。
Mac上でビルドした時も日本語入力はうまくいかなかった。外でクリックしてもなんかバグる。
InputFieldコンポーネントのOn Value Changedに関数を設定する
OnEndEditで確かめてみたので、今度はOnValueChangedで確かめてみたい。
さっきまでOnEndEditにOnEndEdit関数を設定していたので、−ボタンを押して削除しよう。
−ボタンを押して、関数を削除したら、今度はOnValueChanedの方に関数を設定しよう。関数名がOnEndEditのままなので、本来名前としては適切でないと思うが今回は動きを確かめるなのでご愛嬌。
プレイして確かめてみる(OnValueChanged)
OnValueChangedに設定したので、InputFieldに文字を入力する度にこの関数が発動するはずだ。つまりリアルタイムで入力した文字が反映されるはず。
アルファベットは成功!
日本語は、やっぱり反映されず、、
残念ながらOnEndEditに設定した状態と全く同じになった。
外側クリックしたら、反映されるところまで、OnEndEditと一緒だ。
どうやら日本語の場合はダメみたいだ。先ほどと同じようにMac上でビルドしてみたが、うまく反映されなかったので日本語はダメみたい。
日本語入力の場合の解決策
一応、色々記事をググってみたところ、InputFieldコンポーネントのLintTypeをSingleLineからMultiLineNewlineに変更することで、日本語入力が可になるらしい。
MultiLineNewlineはEnter押した時に改行されるってことだ。これで実際にプレイしてみる。ちなみに関数はOnValueChangedに設定している。
日本語入力でEnterを押したら反映されるようになったが、リアルタイムでは変更されない。(OnValueChangedに設定してあるので本来ならリアルタイムに変更されるはずだが、、)
MultiLineNewlineに設定すると、今度はアルファベット入力がうまく反映されなかったりもするので、素直にアルファベットのみを使うほうがいいかもしれない。
でも絶対Unityで作ったゲームで日本語入力した内容を受け取ったり、受け取ったテキストを使用できているはずなので、(そういうゲームたくさんあるよね?)どうにかやり方があると思うのだが、自分の力だとまだうまく出来そうにない。もっと調べて分かり次第追記予定です。
まとめ
- InputFieldのOnValueChangedとOnEndEditに実行したい関数を設定する
- OnValueChangedは入力している時に発動する
- OnEndEditはフォーカスが外れた時に発動する
- 日本語入力はEnter押した段階で消えてしまう
こんなところだろうか。悔しいが、日本語がうまく反映されないと自分がやりたいことが実装できない。しばらくは他のやり方で頑張るしかない。
おまけ
InputFieldの子オブジェクトのTextを取得する方法はダメ?
ここからは読まなくても大丈夫な部分だが、もし気になる人は読んでみてほしい。
最初に、自分がこの実装をどのように実行しようとしたのかというとHierarchy上のInputFieldの子オブジェクトのTextを取得してそれをにDisplayTextに反映するやり方だった。
ややこしいけど、InputFieldコンポーネントのテキストじゃなくて、InputFieldの子のTextオブジェクトを取得ってことだ。
実際にこのやり方で動かしてみたが、OnValueChangedの方でなんかエラーがおきてうまくいかなかった。
たぶん素直にInputFieldコンポーネントのテキストを取得した方がよいと思う。