1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Unity InputSystemで押し続けインタラクション

1
Last updated at Posted at 2025-11-16

コード

書いたのはめちゃくちゃ簡単なコードで、これをアクションやバインドに適用すればそれでperfomedが定期的に呼び出されます。

using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
#if UNITY_EDITOR
using UnityEditor;
[InitializeOnLoad]
#endif
public class MakeIntuitiveInteraction : IInputInteraction
{
#if UNITY_EDITOR
    static MakeIntuitiveInteraction()
    {
        Initialize();
    }
#endif

    [RuntimeInitializeOnLoadMethod]
    static void Initialize()
    {
        InputSystem.RegisterInteraction<MakeIntuitiveInteraction>();
    }

    [Tooltip("リピート間隔")]
    public float repeatInterval = .03f;
    public float deadZone = .2f;

    public static bool IsIntuitiveControl(InputControl control) => control is DeltaControl;
    public void Process(ref InputInteractionContext context)
    {
        if (IsIntuitiveControl(context.control))
        {
            if(context.control.IsPressed())context.Performed();
        }
        else
        {
            // performedの呼び出しタイミングを定期的にするため、呼びだしは以下の二例のみ
            // 最初(waiting => performed)
            // timerHasExpiredの時(performed => performed)
            switch (context.phase)
            {
                case InputActionPhase.Waiting:
                    // 最初の呼び出し
                    if (context.control.IsPressed(deadZone))
                    {
                        context.PerformedAndStayPerformed();
                        context.SetTimeout(repeatInterval);
                    }
                    break;
                case InputActionPhase.Performed:
                    // タイマーイベント中、IsPressed() => performed
                    if (context.timerHasExpired)
                    {
                        if (context.control.IsPressed(deadZone))
                        {
                            context.PerformedAndStayPerformed();
                            context.SetTimeout(repeatInterval);
                        }
                    }
                    // 値変化時、IsNotPressed() => canceled
                    else
                    {
                        if (!context.control.IsPressed(deadZone))
                        {
                            context.Canceled();
                        }
                    }
                    break;
            }
        }
    }
    public void Reset()
    {
    }
}

個人的な考察(InputSystemにない概念)

このコードをどのように使うかという点で、この章を読むとより良いものが作れるかもしれません。

ボタン入力と連続入力

個人的に、全ての入力はこの二つに分類されると考えています。

ボタン入力

・押した、離した、これが重要になる入力です。
・多くが0~1の間で変化します。
・キーボード、ボタンクリック、スティック入力

連続入力

・ユーザーの意思が、細かい連続した入力の総和として表される入力です。
・入力の絶対値が1以上であることが多い。
・マウススクロール、マウス座標変化
・マウスを右に動かしました。このとき(2,1)(4,0)(1,-1)など大量にマウス座標の値の変化が発生し記録されます。ユーザーは、送られた細かい入力の変化を画面で視覚的に感じ取り、目標に達したと感じた時に入力を終了します。

ボタン処理と連続処理

上記の入力が存在すると、自然と処理の概念もそれらを意識したものになります。

ボタン処理

・ボタン入力を意識した処理。
・コマンド入力、メニュー選択など
・wキーを三回押したのは「www」と入力したいから。

連続処理

・連続入力を意識した処理
・マウスカーソル移動、ページスクロール等

ボタン x 連続の組み合わせを意識

当然ながら、ボタン入力で連続処理をしたい、または連続入力でボタン処理をしたい場合には不都合が発生します。

ゲームパッドはすべてボタン入力と言えますが、ゲームパッドでブラウザを操作するのはもどかしく感じませんか?

ボタンを押したときではなく「マウスのフリックを検知したら何らかの操作を実行する」ような機能を作成するのは難しそうですよね?

ボタン入力 x 連続処理

この記事で解決する内容です。InputSystemでは考慮されていませんが、現実的に多発する実装です。

一定期間連続する入力を再現するため、ボタンを押している間、定期的に処理を呼び出す必要があります。

当コードでは「performed状態中に起こったタイムアウトイベント」「waiting状態」で有効な値が入力されていれば、performedして次のタイムアウトイベントを予約します。perfromed状態で発生する値の変化時イベントは無視することでperformed呼び出し頻度を定期的にします。

連続入力 x ボタン処理

連続する入力について、一定期間の総和を解釈してボタンに割り当てる必要があります。

もしかしたら追加で記事を書くかもしれませんが、今日は寝る時間です。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?