1. サイトトップ
  2. ブログ
  3. Unity
  4. 【Unity】Input Systemによる入力管理

【Unity】Input Systemによる入力管理

はじめに

こんにちは!
情熱開発部・プログラム課の千原です!

日が少しずつ長くなってきましたが、まだまだ風の冷たい日々が続いていますね。

さて、今回はUnityInput Systemタッチ操作を中心に見てみたいと思います!

使用するバージョン
Unity:6000.0.58f2

Input Systemとは

Input System は、
キーボードマウスゲームパッドタッチ操作などの入力を統一的に扱うための入力フレームワークです!

従来の Input.GetMouseButton , Input.GetKeyDown関数などのように入力状態を直接確認する方式とは異なり、Input Systemでは 入力をイベントとして扱うことができます。
旧Inputでは、以下のようなコードを書くこともあったと思います。

private void Update()
{
    if (Input.GetMouseButtonDown(0) || Input.GetKeyDown(KeyCode.Enter) || Input.GetButtonDown("A"))
    {
        OnDecision();
    }
}

private void OnDecision()
{
    print("決定!");
}

これは毎フレームに入力を監視する仕組みで、シンプルですが次のような課題があります。

  • デバイス、プラットフォーム対応が大変
    対応するものが増えるほど、コードが肥大化してしまう

  • 入力状態管理が複雑になりやすい
    「押した瞬間」「離した瞬間」など、入力が増えるほど、自前で管理する必要がある

一方、Input SystemではActionを登録しておくことで、「入力が成立した瞬間」に処理を受け取れます。

private void OnEnable()
{
    decisionAction.action.performed += OnDecision;
    decisionAction.action.Enable();
}

private void OnDecision(InputAction.CallbackContext ctx)
{
    if (ctx.phase != InputActionPhase.Performed) return;

    print("決定!");
}

Actionを中心に入力を設計することで、次のようなメリットがあります。

複数デバイス対応が簡単

「決定」Actionとして定義し、
次のような分岐を同じ処理にまとめることができます。

  • マウスクリック
  • Enterキー
  • Aボタン

キーコンフィグやリマップに強い

入力がAction単位で管理されているため、次の仕組みも作りやすくなっています。

  • ボタン配置を後から変更する
  • プレイヤーがキーコンフィグを行う

メリットを確認したところで、Input Systemを扱ううえで必要な機能をみていきましょう!

Interaction

Interactionとは「入力が成立する条件」を決める仕組みのことを指し、条件を満たした瞬間に Performed が発火します。
例えば同じボタン入力でも、

  • Press:押された瞬間
  • Tap:タップしたとき
  • MultiTap:短時間に複数回タップしたとき
  • Hold:一定時間押し続けたとき

といった違いを表現できます。

フェーズ

フェーズとはActionが現在どの入力状態にあるかを表します。
状態の判別Action登録時に使用します。

  • Disabled – Actionが無効化されている状態
  • Waiting – 入力を待機している状態
  • Started – 入力が開始した状態
  • Performed – 入力が条件を満たして成立した状態
  • Canceled – 入力が途中で中断された状態

入力を検知してみる

早速ですが、入力を検知してみましょう!
今回は画面に触れたことを検知してみます!

Input Managerの作成

空のオブジェクトに「Input Manager」のスクリプトを作成して、アタッチします。

コード作成

スクリプトを開いて、以下のコードを追加し、
Performed にOnPress関数を登録して、「入力の条件を満たしたときに呼ばれる」ようにします!

using UnityEngine;
using UnityEngine.InputSystem;

public class InputManager : MonoBehaviour
{
    [Header("触れた"), SerializeField]
    private InputActionProperty pressAction;

    private void OnEnable()
    {
        // Actionに関数を登録する
        pressAction.action.performed += OnPress;

        // Actionの有効化
        pressAction.action.Enable();
    }

    private void OnDisable()
    {
        // Actionに登録した関数を解除する
        pressAction.action.performed -= OnPress;

        // Actionの無効化
        pressAction.action.Disable();
    }

    private void OnPress(InputAction.CallbackContext ctx)
    {
        if (ctx.phase != InputActionPhase.Performed) return;

        print("押された!");
    }
}

InputActionの設定

【Action Mapの設定】

1.「右クリック > Create > Input Actions」からInput Actionを作成して開きます。

2.「+」ボタンからAction Mapsを作成します。

【Actionの追加、設定】

1. Action名「Press」に変更
2.「Action Properties > Interactions」「+」ボタンから、「Press」を選択
3.「<No Binding>」を選択し、「Press」を検索、「Press[Pointer]」を選択

【Input Managerへアタッチ】

1.「Press Action」「Use Reference」に変更
2.先ほど作成したActionを押し、「Press」「Press Action」へドラッグアンドドロップ

【シミュレート設定】

設定をしておくことによって、マウスやペン入力を「タッチ入力として扱うことができるのでオンにしておきます。
1.「Window > Analysis > Input Debugger」から「Input Debug」を開く

2.「Option」から「Simulate Touch Input From Mouse or Pen」を選択し、チェックを入れる

【実行】

ゲームを実行し、画面をクリックするとログが出るのを確認してください!

スマホゲームで使用する機能を紹介

次のスマホゲームでよく使用するものを追加し、ログを出してみましょう!

  • Tap:タップしたとき
  • Hold:一定時間押し続けたとき
  • Delta:移動量 (今回はHoldしているときのみログを出します)

【コード追記】

Input Managerのスクリプトに次のように新しく追記します。

using UnityEngine;
using UnityEngine.InputSystem;

public class InputManager : MonoBehaviour
{
    [Header("触れた"), SerializeField]
    private InputActionProperty pressAction;

    [Header("タップ"), SerializeField]
    private InputActionProperty tapAction;

    [Header("長押し"), SerializeField]
    private InputActionProperty holdAction;

    [Header("移動量"), SerializeField]
    private InputActionProperty deltaAction;

    private void OnEnable()
    {
        // Actionに関数を登録する
        pressAction.action.performed += OnPress;
        tapAction.action.performed += OnTap;
        holdAction.action.performed += OnHold;
        deltaAction.action.performed += OnDelta;

        // Actionの有効化
        pressAction.action.Enable();
        tapAction.action.Enable();
        holdAction.action.Enable();
        deltaAction.action.Enable();
    }

    private void OnDisable()
    {
        // Actionに登録した関数を解除する
        pressAction.action.performed -= OnPress;
        tapAction.action.performed -= OnTap;
        holdAction.action.performed -= OnHold;
        deltaAction.action.performed -= OnDelta;

        // Actionの無効化
        pressAction.action.Disable();
        tapAction.action.Disable();
        holdAction.action.Disable();
        deltaAction.action.Disable();
    }

    private void OnPress(InputAction.CallbackContext ctx)
    {
        if (ctx.phase != InputActionPhase.Performed) return;

        print("押された!");
    }

    private void OnTap(InputAction.CallbackContext ctx)
    {
        if (ctx.phase != InputActionPhase.Performed) return;

        print("タップされた!");
    }

    private void OnHold(InputAction.CallbackContext ctx)
    {
        if (ctx.phase != InputActionPhase.Performed) return;

        print("長押しされた!");
    }

    private void OnDelta(InputAction.CallbackContext ctx)
    {
        // 長押ししている時だけ移動量を取得する
        if (holdAction.action.phase != InputActionPhase.Performed) return;

        // 移動量が0の時はスキップする
        Vector2 delta = ctx.ReadValue<Vector2>();
        if (delta == Vector2.zero) return;

        print($"移動量: {delta}");
    }
}

【TapとHoldの追加、設定】

1. 「Actions」「+」ボタンそれぞれのActionを追加し、Action名を変更
2.「Interactions」「+」ボタンから、それぞれを選択
3.「<No Binding>」を選択し、Pressと同様に「Press[Pointer]」を選択

「Interactions」を変更することで、
たとえば長押しだと、検知されるまでの時間を設定できます。

【Deltaの追加、設定】
1.Delta「Action Type」「Button」から「Value」へ変更
2.「<No Binding>」を選択し、「Delta」を検索、「Delta[Pointer]」を選択

【Input Managerへアタッチ】

Pressと同様にInput Managerへアタッチします。

【実行】

ゲームを実行し、ログを確認してください!
それぞれのログが出ることを確認し、完成です!

最後に

今回はInput Systemについて、旧Inputとの違いを比較し、実際にタッチ操作の実装まで行ってみました。

最初はInteractionフェーズActionなどといった新しい概念が出てきて少々難しく感じるかもしれませんが、
慣れてくると入力処理を非常に整理・管理しやすくなります。

マルチプラットフォーム開発でも便利な機能なので、ぜひ一度触って導入してみてください!

参考


【免責事項】

本サイトでの情報を利用することによる損害等に対し、
株式会社ロジカルビートは一切の責任を負いません。