【Unity】Input Systemで入力された文字を取得する

こじゃらこじゃら

Input Systemでキーボードから入力された文字を知りたい場合はどうすればいいの?

このはこのは

Keyboardクラスから取得できるわ。基本的にコールバック経由で取得することになるわ。

Input Systemでキーボードのテキスト入力を取得する方法の解説記事です。

これは、Keyboard.onTextInputイベントから取得できます。

// 入力された文字をログ出力
Keyboard.current.onTextInput += ch => print(ch);

基本的に、デバイス依存のコードを書くことになりますが、公式が推奨する取得方法です。

Input Action経由でも取得は一応可能ですが、リソースを多く消費するため公式では推奨されていません。

参考:具体的な操作方法 | Input System | 1.4.3

本記事では、Keyboardクラスを通じてキーボードから入力された文字を取得する方法を解説します。また、IME入力の取得方法についても解説します。

注意

Input System 1.6.1現在では、IMEによる日本語入力について一部正常動作しないことを確認しました。使用する際はご注意ください。

動作環境
  • Unity 2023.1.0f1
  • Input System 1.6.1

スポンサーリンク

前提条件

事前にInput Systemがインストールされ、有効化されているものとします。

導入方法および基本的な使い方は、以下記事をご覧ください。

入力された文字を取得する

KeyboardクラスのonTextInputプロパティを通じて取得できます。

public event Action<char> onTextInput

キーボードから文字入力があった際にコールバックとして呼ばれ、引数に入力された文字が渡されます。

参考:Class Keyboard | Input System | 1.6.1

その他の方法として、Input Action経由から取得することも考えられますが、公式では推奨されていません。 [1]

参考:具体的な操作方法 | Input System | 1.4.3

サンプルスクリプト

以下、キーボードから入力された文字を取得し、文字コードと共にログ出力する例です。

GetTextExample.cs
using UnityEngine;
using UnityEngine.InputSystem;

public class GetTextExample : MonoBehaviour
{
    private void OnEnable()
    {
        var keyboard = Keyboard.current;
        if (keyboard == null) return;

        // キーボードの入力を受け取る
        keyboard.onTextInput += OnTextInput;
    }

    private void OnDisable()
    {
        var keyboard = Keyboard.current;
        if (keyboard == null) return;

        // キーボード入力の受取り解除
        keyboard.onTextInput -= OnTextInput;
    }

    private void OnTextInput(char ch)
    {
        // 入力された文字を文字コード(16進数)と共に表示
        print($"OnTextInput: {ch}({(int) ch:X02})");
    }
}

上記をGetTextExample.csという名前でUnityプロジェクトに保存し、適当なゲームオブジェクトにアタッチすると機能します。

実行結果

キーボードから文字を入力されるたびに、文字コード(16進数)と共にログ出力されるようになりました。

スクリプトの説明

コンポーネントが有効になったら、以下処理でonTextInputプロパティにコールバックを登録しています。

private void OnEnable()
{
    var keyboard = Keyboard.current;
    if (keyboard == null) return;

    // キーボードの入力を受け取る
    keyboard.onTextInput += OnTextInput;
}

コールバックでは、引数に入力された文字がchar型として渡されます。

private void OnTextInput(char ch)
{
    // 入力された文字を文字コード(16進数)と共に表示
    print($"OnTextInput: {ch}({(int) ch:X02})");
}

コールバックの解除はコンポーネントが無効になった時に行っています。

private void OnDisable()
{
    var keyboard = Keyboard.current;
    if (keyboard == null) return;

    // キーボード入力の受取り解除
    keyboard.onTextInput -= OnTextInput;
}

装飾キーの扱い

Shift、Control、Altキーといった装飾キーは、それ自体の入力を受け取らず、装飾キーによって変更された入力文字を受け取ります。

例えば、Shift + aキーでは「A」という大文字を入力文字として受け取ります。

参考:Keyboard support | Input System | 1.6.1

推奨されない方法

上記で解説した方法以外にも、Input Actionなどを通じて取得することも可能です。

// この方法でも入力されたキーは取得されるが、リソースを大量に消費する
InputAction action = new InputAction(
    "Text",
    InputActionType.PassThrough,
    "<Keyboard>/<Button>"
);

ただし、この方法はキーボードの各キー毎にControlを生成するため、大量のInput Controlが生成されリソースを大量消費することになります。

生成されたControl一覧

また、装飾キーも1つのキー入力として認識されるため、大文字のAなどの文字入力を認識できません。

このような入力を自前で解析するような方法は公式で推奨されていません。基本的にKeyboard.onTextInputイベント経由で入力を取得することが望まれます。

参考:具体的な操作方法 | Input System | 1.4.3

IMEに対応する

日本語入力などといったIME(Input Method Editor)の入力文字の受取り機能もサポートしています。

「あいうえお」などのように文字列が入力され、Enterキーなどで確定すると、Keyboard.onTextInputイベントで1文字ずつ確定した文字列を受け取ることができます。

また、IMEで入力途中の文字列は、変更がある度Keyboard.onIMECompositionChangeイベントから取得できます。

public event Action<IMECompositionString> onIMECompositionChange

引数にはIMECompositionString構造体として文字列情報を受け取ることが出来ます。

参考:Struct IMECompositionString | Input System | 1.6.1

文字列はToStringメソッドのほか、Countプロパティインデクサを使用して取得することが可能です。 [2]

サンプルスクリプト

以下、IME経由で入力されている途中の文字列と、入力が確定した文字(1文字ずつ)をログ出力するサンプルです。

IMEExample.cs
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.LowLevel;

public class IMEExample : MonoBehaviour
{
    private void OnEnable()
    {
        var keyboard = Keyboard.current;
        if (keyboard == null) return;

        // キーボードの入力を受け取る
        keyboard.onTextInput += OnTextInput;
        keyboard.onIMECompositionChange += OnIMECompositionChange;
    }


    private void OnDisable()
    {
        var keyboard = Keyboard.current;
        if (keyboard == null) return;

        // キーボード入力の受取り解除
        keyboard.onTextInput -= OnTextInput;
        keyboard.onIMECompositionChange -= OnIMECompositionChange;
    }

    // 入力された文字を文字コード(16進数)と共に表示
    private void OnTextInput(char ch)
    {
        print($"OnTextInput: {ch}({(int) ch:X02})");
    }
    
    // IMEの入力中の文字列を受け取る
    private void OnIMECompositionChange(IMECompositionString str)
    {
        print($"OnIMECompositionChange: {str}");
    }
}

上記をIMEExample.csという名前でUnityプロジェクトに保存し、適当なゲームオブジェクトにアタッチすると機能します。

本記事では、IME入力を有効にするために、画面上にInput FieldのUIを配置するものとします。

実行結果

Input Fieldにフォーカスしてから日本語入力すると、入力途中の文字列が更新されるたびにその途中結果の文字列が出力されます。

また、入力が確定すると、その文字列が一文字ずつonTextInputイベントに渡されて表示されていることも確認できます。

スクリプトの説明

IME入力途中の文字列受取りは、onIMECompositionChangeイベントにコールバック登録することで行います。

keyboard.onIMECompositionChange += OnIMECompositionChange;

コールバックでは、受け取った引数の情報をそのままログ出力しています。

// IMEの入力中の文字列を受け取る
private void OnIMECompositionChange(IMECompositionString str)
{
    print($"OnIMECompositionChange: {str}");
}

コールバック登録解除もonTextInputと同じ要領です。

keyboard.onIMECompositionChange -= OnIMECompositionChange;

既知の不具合について

Keyboardクラスには、IMEを有効にするSetIMEEnabledメソッドが存在します。

public void SetIMEEnabled(bool enabled)

しかし、当環境 [3] で検証した結果、IMEが有効化されないことを確認しました。

なお、次のように旧InputのimeCompositionModeプロパティ経由で指定すると有効になるようです。

Input.imeCompositionMode = IMECompositionMode.On;

上記処理は、Input Fieldでフォーカスが有効になった瞬間に内部的に呼ばれているようです。フォーカスが外れると、次の処理でIMEをAutoに切り替えているようです。

Input.imeCompositionMode = IMECompositionMode.Auto;

上記処理に限っては、旧Inputが無効になっていても使用できるようです。

参考:Class Keyboard | Input System | 1.6.1

参考:Input-imeCompositionMode – Unity スクリプトリファレンス

参考:該当のソースコード

さいごに

Input Systemでキーボードから入力された文字を取得するには、Keyboard.onTextInputイベントを使います。

日本語入力などの文字は、Keyboard.onTextInputのほか、Keyboard.onIMECompositionChangeイベントから途中結果のものを取得できます。

IMEについては一部機能しないメソッドなどもあり、それらに注意しながら使うと良いでしょう。

参考サイト

スポンサーリンク