【MRTK】MRTKInputFieldが使いづらい 解決案

# はじめに
開発中のHoloLens2アプリのログイン周りの入力がやりづらかったので解決策を探りました。

# 環境
+ HoloLens2
+ Windows 10 pc
+ Unity 2019.4.1f1

# 仕様
アプリの仕様
E-mailとパスワードを半角英数字で入力してログインする仕様です。
HoloLens2標準キーボード+MRTK標準InputFieldを使用していました。

MRTK標準InputFieldの仕様
InputField ContentType は指定した形式以外の入力が確定したときにブロックします。
ContentType Email を指定したときも全角文字を入力することができてEnterを押したときに消えます。

# 問題点
Email、パスワードの半角英数字が入力しづらい状態です。
理由は下の問題があるためです。

+ 全角入力から始まる。
+ 全角の文字を入力すると二重に表示される。
+ 全角の文字を入力すると1文字ずつしか表示されないことがある。
+ HoloLens2を慣れていないユーザーから見ると半角文字と全角文字の区別が難しい。

# 対処法

対処法として以下の方法を考えました。

+ 入力文字を無理やり半角に変える。
+ 全角文字が入力されたときにユーザーに知らせる。
+ 半角英数字しか入力できないキーボードを使用する。
+ ログイン方法を変更する。

# 入力文字を無理やり半角に変える
## やり方
```C#:Validation.cs
using Microsoft.MixedReality.Toolkit.Experimental.UI;
using UnityEngine;

public class Validation : MonoBehaviour
{
    [SerializeField] MRTKTMPInputField InputField = default;

    FullWidthToHalfWidthConverter converter = new FullWidthToHalfWidthConverter();

    private void Awake()
    {
        if(InputField == null)
            InputField = GetComponent<MRTKTMPInputField>();
        
        InputField.onValueChanged.AddListener(ConvertToHalfWidth);
    }

    private void ConvertToHalfWidth(string text)
    {
        if (!converter.IsHalfWidth(text))
        {
            InputField.text = converter.Convert(text);
        }
    }
}
```

```C#:FullWidthToHalfWidthConverter.cs
public class FullWidthToHalfWidthConverter
{
    private Encoding encoding = Encoding.GetEncoding("Shift_JIS");

    private Dictionary<char, char> FullWidthToHalfWidthDictionary = new Dictionary<char, char>
    {
        { 'ー','-'},
        { '「','['},
        { '」',']'},
        { '、',','},
        { '。','.'},
        { '・','/'},
    };

    private const int FullWidthHalfWidthDifference = 65248;
    private const int StartFullWidthCharSetByte = 65281;
    private const int EndFullWidthCharSetByte = 65374;

    public string Convert(string text)
    {
        string output = "";
        foreach (int c in text)
        {
            if (StartFullWidthCharSetByte <= c && c <= EndFullWidthCharSetByte)
            {
                output += (char)(c - FullWidthHalfWidthDifference );
                continue;
            }

            if (FullWidthToHalfWidthDictionary.Keys.Any(k => (int)k == c))
            {
                output += FullWidthToHalfWidthDictionary[(char)c];
                continue;
            }

            output += (char)c;
        }

        return output;
    }

    public bool IsHalfWidth(string text)
    {
        return text.Length == encoding.GetByteCount(text);
    }
}
```
上のコードをプロジェクトに追加して Validation を MRTKInputField にアタッチする。
## デメリット
入力中の文字が二重に表示される、一文字しか表示されないなどの問題は解決できない。
全角のaなどの入力はひらがなに変換されてしまう。

# 全角文字が入力されたときにユーザーに知らせる
## やり方
```C#:ValidationMessage.cs
using System.Text;
using TMPro;
using UnityEngine;

public class ValidationMessage : MonoBehaviour
{
    [SerializeField] TextMeshProUGUI Text = default;

    private Encoding encoding = Encoding.GetEncoding("Shift_JIS");

    public void CheckText(string text)
    {
        if(!IsHalfWidth(text))
        {
            Text.text = "全角入力中です";
        }
        else
        {
            Text.text = "";
        }
    }

    private bool IsHalfWidth(string text)
    {
        return text.Length == encoding.GetByteCount(text);
    }
}
```
上のスクリプトをプロジェクトに追加して適当なオブジェクトにアタッチする。
Inspectorから表示先のテキストを ValidationMessage.Textプロパティに設定。
バリデーション対象の MRTKInputField の OnValueChanged に ValidationMessage.CheckTextを追加。
## デメリット
扱いづらさを軽減することはできるが、解決はできない。
# 半角英数字しか入力できないキーボードを使用する
## やり方
NonNativeKeyboardを使用する。

https://qiita.com/h_koya/items/d26034eef69d99f0abd1
## デメリット
変換機能を使用することができない。
キーボードを表示する場所等の調整が大変。

# ログイン方法を変更する
PINやQRコード等を使用し、文字入力を使用せずにログインできるようにする。
## デメリット
HoloLens2単体でのログインが困難。
バックエンドにも変更が必要。
セキュリティ面に注意する必要がある。

# 結論
現在開発中のアプリでは NonNativeKeyboardを使用したログインと PIN認証を選択できるようにすることにしました。
理由はHoloLens2単体でのログインとストレスのないログインを両方サポートしたかったからです。
まだログイン周りの入力方法は検討を続ける予定です。
他の方法ご存じの方いらっしゃいましたらご教授いただけると幸いです。