原カバンは鞄のお店ではありません。

Unityを使ったゲーム制作のあれこれを綴っていきます。

【Unity】InputSystemにオリジナルの入力パターンを追加して連打を判定する

エイプリルフール

SNS上での企業や芸能人等々のエイプリルフール投稿に花冷えの風邪をひきそうな冷笑系の皆さんこんにちは。なんであんなにウキウキで寒いネタを投稿できるのでしょうか?もう飽きたのでいっそのことエイプリルフール自体を廃止にしても良いと思う。

 

連打を判定したい

作成中のリズムゲーム「Under A Groove」について前回はリズムゲームなら定番のホールド(長押し)の入力判定をInputSystemを利用して実装することができました。

www.karvan1230.com

今回はそれに引き続き「連打」の入力判定を取り入れるたいと思ったのですが、ホールド(長押し)とは異なり「連打」の場合はInputSystemにはそれを判定するような入力パターンは定義されていません。
まぁ、単純にUpdateなどで一定時間内に発生するキー/ボタン押下のイベントの回数を判定すれば実装できそうな気もしますが、入力デバイスがキーボード/ゲームパッド等々と複数存在する場合は判定が面倒なことと、どうせならこういった入力判定はInputSystemで一元管理したいので、「連打」を判定する為の入力パターンをInputSystem側に登録し、それを使って判定を実装することにしました。

 

Interaction

InputSystemではPress(単押し)やHold(長押し)、Tap(押して離す)などの入力に関してはプリセットとして用意されていますが、それ以外の入力パターンを判定したい場合にそれを自作して登録することができます。

自作のInteractionは、IInputInteractionインタフェースを実装したクラスとして作成し、アプリケーション初期化などのタイミングでInteractionを登録する処理を呼び出します
IInputInteractionインタフェースにはProcessとResetの二種類のメソッドが用意されており、そのうちProcessメソッド側に必要な入力パターンの判定処理を実装します。

using UnityEngine;
using UnityEngine.InputSystem;

public class MashInteraction : IInputInteraction
{
#if UNITY_EDITOR
    [UnityEditor.InitializeOnLoadMethod]
#else
    [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
#endif

    public static void Initialize()
    {
        // 初期処理でInteractionをInputSystemに登録する
        InputSystem.RegisterInteraction<MashInteraction>();
    }

    public void Process(ref InputInteractionContext context)
    {
        // TODO : Interactionの処理
    }
    
    public void Reset()
    {
        // TODO : Interactionの状態をリセットする処理
    }
}

上記をMashInteraction.csという名前でUnityプロジェクトに保存すると、Input System側にInteractionとして「Mash」という名前で表示され使用できるようになります。

 

状態遷移について

InputSystemでは内部に状態(ステート)を持っており特定の条件を満たすと状態(ステート)が他の状態に遷移することでイベントを発火→上位へコールバック通知する、という仕組みとなっています。

上図の星マークがある状態へ遷移したときにそれぞれに応じたイベントが発火する仕組みですが、Performed状態の場合はその状態が継続される場合(PerformedからPerformedへ遷移)もイベントが発火します。

 

連打判定について

この状態遷移を「連打」の判定に利用する場合は、Performedへ遷移する条件を「特定の秒数(T秒)以内に指定の回数(N回)ボタンが押下された」場合とする事で「連打」中の状態を判定し、「T秒以内にN回押されなかった」場合にCanceled状態へ遷移させれば「連打」中でない状態になったことを上位へ通知することができます。

この為、先ほどのMashInteractioクラスに「特定の秒数」を指定するための変数(tapTimeOut)、「指定の回数」を指定するための変数(reqTapCount)を用意し、併せてボタン押下判定用の閾値を用意します。

// 連打判定の最大許容時間間隔[s]
public float tapTimeOut;

// 入力判定閾値
public float pressPoint;

// 連打判定に必要な回数
public int reqTapCount = 2;

public void Process(ref InputInteractionContext context)
{
    // 入力値の大きさ閾値以上かどうか
    if (context.ControlIsActuated(pressPoint)) {
        // ボタンが押された時の処理
    }
}

ここで入力値の判定はProcessメソッドに引数として渡されるInputInteractionContextクラスを利用している事に注目してください。
Interactionの各状態への遷移は、このInputInteractionContextクラスの次のメソッドにより行います。

  • Started() – Startedフェーズへ遷移する
  • Performed() – Performedフェーズへ遷移する
  • PerformedAndStayPerformed() – Performedフェーズへ遷移し、そのままPerformedフェーズに留まる
  • PerformedAndStayStarted() – Performedフェーズへ遷移し、その後Startedフェーズへ遷移する
  • Canceled() – Canceledフェーズへ遷移する

そして、「特定の秒数」を判定するためのタイムアウト処理にはInputInteractionContextクラスのSetTimeoutメソッド、「特定の秒数」入力がないタイムアウトが発生したかの判断にはInputInteractionContextクラスのtimerHasExpiredプロパティを使用します。

これらを利用したProcess内での「連打」判定の処理シーケンスとしては以下のようになります。

 

Interactionの適用

上記までの内容でIInputInteractionインタフェースを実装したクラスを作成するとInputSystemで利用することができます。プロジェクト内のInput Actionsアセットをダブルクリックしてウィンドウを開きます。Input Actionsアセットを作成していない場合は先にInput Actionsアセットを作成する必要があります。

Actions名に「Mash」という名に設定し、+アイコンから入力デバイスを追加、右のBindingProperties欄のInteractionに「Mash」が追加されているので、それを選択し「連打」によるイベントの通知を設定します。
作成したInteractionでpublic変数として用意した変数を使って判定に必要な値を設定することができます。

 

実行結果

ボタンを短い時間間隔(tapTimeOutに設定した時間以内)で押下すると「連打」状態と判定し、その間のボタン押下時にエフェクト(緑のサークル)を表示されるようにしています。

 

ボタンを一定時間操作(押したり離したり)しなければ、canceledコールバックが実行されて終了します。
新規にクラスを作成してTimeoutを使ったりと少々面倒くさい実装かもしれませんが、update内で実装するよりはスマートであること、InputSystemにて入力イベントを一元管理できることを考えると、こういった用途にオリジナルのInteractionを作る手法は適していると思います。

 

◇プライバシーポリシー

●個人情報の利用目的

当ブログでは、メールでのお問い合わせ、メールマガジンへの登録などの際に、名前(ハンドルネーム)、メールアドレス等の個人情報をご登録いただく場合がございます。

これらの個人情報は質問に対する回答や必要な情報を電子メールなどをでご連絡する場合に利用させていただくものであり、個人情報をご提供いただく際の目的以外では利用いたしません。

●個人情報の第三者への開示

当サイトでは、個人情報は適切に管理し、以下に該当する場合を除いて第三者に開示することはありません。

・本人のご了解がある場合
・法令等への協力のため、開示が必要となる場合

個人情報の開示、訂正、追加、削除、利用停止
ご本人からの個人データの開示、訂正、追加、削除、利用停止のご希望の場合には、ご本人であることを確認させていただいた上、速やかに対応させていただきます。

アクセス解析ツールについて

当サイトでは、Googleによるアクセス解析ツール「Googleアナリティクス」を利用しています。

このGoogleアナリティクスはトラフィックデータの収集のためにCookieを使用しています。このトラフィックデータは匿名で収集されており、個人を特定するものではありません。
この機能はCookieを無効にすることで収集を拒否することが出来ますので、お使いのブラウザの設定をご確認ください。

●免責事項

当サイトからリンクやバナーなどによって他のサイトに移動された場合、移動先サイトで提供される情報、サービス等について一切の責任を負いません。

当サイトのコンテンツ・情報につきまして、可能な限り正確な情報を掲載するよう努めておりますが、誤情報が入り込んだり、情報が古くなっていることもございます。

当サイトに掲載された内容によって生じた損害等の一切の責任を負いかねますのでご了承ください。

●プライバシーポリシーの変更について

当サイトは、個人情報に関して適用される日本の法令を遵守するとともに、本ポリシーの内容を適宜見直しその改善に努めます。

修正された最新のプライバシーポリシーは常に本ページにて開示されます。