キーボードで操作する (入力システムパッケージ版)

ページ更新日 :
ページ作成日 :

検証環境

Windows
  • Windows 11
Unity エディター
  • 2020.3.25f1
入力システムパッケージ
  • 1.2.0

この Tips の前提設定

この Tips の説明の前提として以下の設定を事前に行っています。

特定のキーを押した瞬間を判定する

キーを押したらオブジェクトを移動させるという処理を行ってみます。Canvas に移動確認用のテキストオブジェクトを配置しておきます。 サイズや位置は適当でかまいません。

キーボードの処理はスクリプトで行います。ここでは KeyboardOneFrame という名前で作成しています。

コードは以下のようにします。

using UnityEngine;
using UnityEngine.UI;           // 追加
using UnityEngine.InputSystem;  // 追加

public class KeyboardOneFrame : MonoBehaviour
{
  /// <summary>移動させるテキストオブジェクト。</summary>
  [SerializeField] private Text TextObject;

  // 更新はフレームごとに1回呼び出されます
  void Update()
  {
    if (TextObject == null)
    {
      Debug.Log($"{nameof(TextObject)} が null です。");
      return;
    }

    // キーボードの情報を取得
    var keyboard = Keyboard.current;
    if (keyboard == null)
    {
      Debug.Log("キーボードがありません。");
      return;
    }

    var transform = TextObject.transform;

    // wasPressedThisFrame は押した瞬間のみ true となる
    // キーは「keyboard[Key.RightArrow]」のような指定の仕方もある
    if (keyboard.leftArrowKey.wasPressedThisFrame)
    {
      transform.Translate(-1, 0, 0);
    }
    if (keyboard.rightArrowKey.wasPressedThisFrame)
    {
      transform.Translate(1, 0, 0);
    }
    if (keyboard.upArrowKey.wasPressedThisFrame)
    {
      transform.Translate(0, 1, 0);
    }
    if (keyboard.downArrowKey.wasPressedThisFrame)
    {
      transform.Translate(0, -1, 0);
    }
  }
}

Keyboard.current から現在のキーボードのキーの押下状態などが取得できます。 keyboard.xxxxxxx.wasPressedThisFrame はキーを押した瞬間のタイミングだけ true を返すようになっています。 このコードではカーソルキーを押した瞬間であれば Text オブジェクトの transform に対して移動処理を行うようにしています。 押した瞬間のみ処理しているため、キーを押しっぱなしにしても移動は継続されません。

スクリプトを保存したら EventSystem オブジェクトに KeyboardOneFrame をアタッチし、 Text Object に移動対象のテキストオブジェクトをセットしてください。

ゲームを実行しカーソルキーを押したときに@マークが移動するか確認してみてください。 また、キーを押しっぱなしにしても@マークが移動しないことを確認してください。

判定できるキーの種類について

公式サイトの方に書いてあるのでそちらを確認してください。

特定のキーを離した瞬間を判定する

サンプルは作成しませんが、押した瞬間が wasPressedThisFrame プロパティで判定するのに対し離した瞬間は wasReleasedThisFrame で判定できます。

特定のキーを押している間判定する

こちらも同様にスクリプトで判定します。先ほどのコードに追記してもいいですが今回は新しく KeyboardPress というスクリプトファイルを作成して記述します。

スクリプトは以下のようにします。

using UnityEngine;
using UnityEngine.UI;           // 追加
using UnityEngine.InputSystem;  // 追加

public class KeyboardPress : MonoBehaviour
{
  /// <summary>回転させるテキストオブジェクト。</summary>
  [SerializeField] private Text TextObject;

  // 更新はフレームごとに1回呼び出されます
  void Update()
  {
    if (TextObject == null)
    {
      Debug.Log($"{nameof(TextObject)} が null です。");
      return;
    }

    // キーボードの情報を取得
    var keyboard = Keyboard.current;
    if (keyboard == null)
    {
      Debug.Log("キーボードがありません。");
      return;
    }

    var transform = TextObject.transform;

    // isPressed は押している間はずっと true となる
    // キーは「Keyboard.current[Key.Space]」のような指定の仕方もある
    if (keyboard.spaceKey.isPressed)
    {
      transform.Rotate(0, 0, 1);
    }
  }
}

スペースキーを押している間はテキストオブジェクトが回転するような処理を入れています。 keyboard.xxxxxxxx.isPressed はキーを押している間はずっと true を返します。

保存したスクリプトは EventSystem にアタッチして Text Object に回転させるテキストオブジェクトをセットしてください。

ゲームを実行しスペースキーを押している間は@マークがずっと回転することを確認してください。

押しているキーを全て取得する

押しているキーをすべてテキストで表示させてみます。押しているキーを表示するためのテキストオブジェクトを配置しておきます。

KeyboardAllKeys という名前でスクリプトを作成します。

スクリプトは以下のようにします。

using System.Linq;
using UnityEngine;
using UnityEngine.InputSystem;  // 追加
using UnityEngine.UI;           // 追加

public class KeyboardAllKeys : MonoBehaviour
{
  /// <summary>移動させるテキストオブジェクト。</summary>
  [SerializeField] private Text TextObject;

  // 更新はフレームごとに1回呼び出されます
  void Update()
  {
    if (TextObject == null)
    {
      Debug.Log($"{nameof(TextObject)} が null です。");
      return;
    }

    // キーボードの情報を取得
    var keyboard = Keyboard.current;
    if (keyboard == null)
    {
      Debug.Log("キーボードがありません。");
      TextObject.text = "";
      return;
    }

    // allKeys からすべてのキーの情報を走査し isPressed で押しているキーのみを抽出する
    TextObject.text = string.Join(", ", keyboard.allKeys.Where(x => x.isPressed).Select(x => x.keyCode.ToString()));
  }
}

keyboard.allKeys では全てのキーの情報を取得することができます。 それらのキーから isPressed が true のもののみを抽出すると押しているキーのみを取得することができます。 後は押しているキーを文字列化してテキストとして表示させています。

作成したスクリプトは EventSystem にアタッチして押下キー表示用テキストオブジェクトをセットします。

ゲームを実行して押しているキーが表示されることを確認します。

ちなみに沢山のキーを押しても全てのキーが表示されないことがありますが、それはキーボードの配線による物理的な問題なので気にしないでください。

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

これまでは押したキーの種類を取得していましたが、実際に入力した文字を取得することも可能です。 例えば 「A」キーが押された場合は「a」という文字を取得でき「Shift+A」キーが押された場合は「A」という文字が取得できます。 IME が有効であれば日本語も取得できる場合もあります。

ただしこれらの入力された文字はプロパティで取得することはできずイベントという形で取得することになります。

サンプルでは入力した文字を表示させるためのテキストオブジェクトを配置しています。

スクリプトを作成します。名前は KeyboardTextInput とします。

スクリプトは以下のように入力します。

using UnityEngine;
using UnityEngine.InputSystem;  // 追加
using UnityEngine.UI;           // 追加

public class KeyboardTextInput : MonoBehaviour
{
  /// <summary>移動させるテキストオブジェクト。</summary>
  [SerializeField] private Text TextObject;

  /// <summary>
  /// オブジェクトが有効になったときに呼ばれるイベント。
  /// </summary>
  public void OnEnable()
  {
    // 文字が入力されたときに呼ばれるイベントをセット
    Keyboard.current.onTextInput += OnTextInput;
  }

  /// <summary>
  /// オブジェクトが無効になったときに呼ばれるイベント。
  /// </summary>
  public void OnDisable()
  {
    // 文字が入力されたときに呼ばれるイベントを解除
    Keyboard.current.onTextInput -= OnTextInput;
  }

  /// <summary>
  /// 文字を入力するたびに呼ばれる。
  /// </summary>
  /// <param name="c">入力された文字。</param>
  public void OnTextInput(char c)
  {
    TextObject.text += c;
  }
}

Keyboard クラスに onTextInput というイベントがあり、このイベントはテキストが入力されるたびに呼ばれます。 ここでは OnEnable のタイミングで OnTextInput メソッドを登録し、OnDisable のタイミングで OnTextInput を解除しています。 Keyboard.current はゲームが実行されてから終了されるまで唯一無二で存在するオブジェクトなので OnDisable のタイミングなどで必ず解除してください。 イベントの登録と解除を必ず対にできるなら他のタイミングで設定しても問題ありません。

OnTextInput メソッドでは入力された文字が引数 c に設定されるのでテキストとして追記表示するようにしています。

スクリプトを保存したら EventSystem にアタッチして表示用テキストオブジェクトをセットします。

ゲームを実行してキーを押してみてください。文字が入力されるはずです。Shift キーと同時に押せば大文字や記号も入力できるはずです。 また IME が有効なら日本語も入力できます。逆にカーソルキーなど文字にならないキーを押した場合はなにも起こりません。