Interaction
Interaction は、特定の入力パターンを表します。例えば、hold という Interaction では、Control を最小時間以上、押し続けることが求められます。
Interaction により、Action での応答が駆動されます。これらは個々の Binding に配置することも、Action 全体に配置することもできます。後者の場合は、Action 上のすべての Binding に適用されます。ランタイムに特定の Interaction が完了すると、Action がトリガーされます。
操作
Interaction には、入力を受け取ると通過する一連の明確なフェーズ (段階) があります。
フェーズ | 説明 |
---|---|
Waiting |
Interaction は入力を待機しています。 |
Started |
Interaction は開始されました (つまり、想定された入力の一部が受け取られました) が、まだ完了していません。 |
Performed |
Interaction は完了しました。 |
Canceled |
Interaction は中断され、終了しました。例えば、ユーザーがボタンを押した後、hold Interaction の完了に必要な最小時間が経過する前にボタンを放しました。 |
すべての Interaction がすべてのフェーズをトリガーするとは限りません。特定の Interaction がフェーズをトリガーするパターンは、Interaction のタイプによって異なります。
通常、Interaction に対する実際の応答をトリガーするフェーズは Performed
です。また、Started
と Canceled
は、Interaction の進行中に UI フィードバックを提供するために役立ちます。例えば、hold が Started
になると、アプリケーションでプログレスバーを表示して、押し続ける必要のある時間が経過するまで進行状況をバーに表示することができます。hold が完了する前に Canceled
になった場合は、アプリケーションでプログレスバーを、開始時の状態にリセットします。
以下の例は、このような設定を fire (発砲) Action で使用する方法を示しています。ユーザーがタップするとすぐに発射し、押したままにするとチャージすることができます。
var fireAction = new InputAction("fire");
fireAction.AddBinding("<Gamepad>/buttonSouth")
// タップで発砲し、長押しタップでチャージします。どちらも放したときに作動します。
.WithInteractions("tap;slowTap");
fireAction.started +=
context =>
{
if (context.Interaction is SlowTapInteraction)
ShowChargingUI();
};
fireAction.performed +=
context =>
{
if (context.Interaction is SlowTapInteraction)
ChargedFire();
else
Fire();
};
fireAction.canceled +=
_ => HideChargingUI();
Action 上の複数の Control
Interaction を含む Binding または Action に複数の Control がバインドされている場合、Input System では、最初に Control の競合解決 ロジックを適用して Action の単一の値が取得され、その値が Interaction のロジックに渡されます。バインドされているどの Control にも、Interaction を実行する可能性があります。
Binding 上の複数の Interaction
1 つの Binding または Action に複数の Interaction が存在する場合は、Binding に出現する順に Interaction が処理されます。前述 のコード例は、この例を示しています。fireAction
Action の Binding には、WithInteractions("tap;slowTap")
によって 2 つの Interaction が設定されています。Action からの入力の解釈時に、最初に処理されるのは tap Interaction です。ボタンが押されると、Action によって tap Interaction で Started
コールバックが呼び出されます。ユーザーがボタンを押し続けると、tap Interaction がタイムアウトになり、Action から tap Interaction に対して Canceled
コールバックが呼び出され、SlowTap Interaction (これが Started
コールバックを受け取ります) の処理が開始されます。
どの時点でも、アクションを "駆動" できる Interaction (これで、アクションの現在の phase
が決定されます) は、一度に 1 つだけです。スタックの上位にある Interaction がキャンセルされると、下位にある Interaction が、その役割を引き継ぎます。
タイムアウト
Interaction では、特定の入力が発生するか、発生しないかが決まるまでに、一定時間の待機が必要になる場合があります。これに該当する例が Hold Interaction です。この Interaction では、ボタンが押されてから "hold" が完了するまで、duration で設定された時間が経過するのを待つ必要があります。これを実現するために、Interaction は SetTimeout
を使用してタイムアウトをインストールします。
場合によっては、Interaction が完了するまでのタイムアウトの残り時間を把握できると便利です。例えば、Interaction の完了を待っている間、進行状況を示すバーを UI に表示することができます。完了したタイムアウトの割合を照会するには、GetTimeoutCompletionPercentage
を使用します。
// 0 から 1 の範囲 (0 と 1 を含む) の値を返します。
var warpActionCompletion = playerInput.actions["warp"].GetTimeoutCompletionPercentage();
各 Interaction には、独自のタイムアウトを個別に設定できることに注意してください (ただし、一度に設定できるタイムアウトは 1 つだけです)。複数の Interaction が有効になっている場合、GetTimeoutCompletionPercentage
では、現在、アクションを駆動している 1 つの Interaction のタイムアウトだけが使用されます。
Interaction によっては、複数のタイムアウトが連続で発生することがあります。この場合、現在実行中のタイムアウト (ある場合) が完了したことだけがわかっても、多くの場合は役に立ちません。例えば、MultiTapInteraction
には、個々のタップごとのタイムアウトと、タップ間のタイムアウトが設定されています。Interaction は、タップシーケンス全体が実行された後にのみ完了します。
Interaction では、SetTotalTimeoutCompletionTime
を使用して、タイムアウトまでの合計時間を Input System に知らせることができます。
Interaction の使用
Interaction は、Binding または Action にインストールできます。
Binding への Interaction の適用
Action の Binding を作成するときに、Binding に Interaction を加えることができます。
Input Action アセット を使用している場合は、Input Action エディターで Binding に任意の Interaction を設定できます。いくつかの Binding を作成 したら、Interaction を加える Binding を選択します。これにより、ウィンドウの右ペインに、その Binding のプロパティが表示されます。次に、Interactions フォールドアウトのプラス記号アイコンをクリックして、使用できるすべての Interaction タイプのリストを開きます。いずれかの Interaction タイプを選択して、そのタイプの Interaction インスタンスを加えます。これで、Interaction が Interactions フォールドアウトに表示されます。Interaction にパラメーターがある場合は、ここで編集できます。
Interaction を削除するには、その横にあるマイナス記号ボタンをクリックします。Interaction の順序 を変更するには、上下の矢印をクリックします。
コードで Binding を作成する場合は、以下のように Interaction を指定できます。
var Action = new InputAction();
action.AddBinding("<Gamepad>/leftStick")
.WithInteractions("tap(duration=0.8)");
Action への Interaction の適用
Action に直接 Interaction を適用すると、その Action のすべての Binding に Interaction を適用した場合と同じになります。これは、同じ Interaction を手動で各 Binding に設定する手間を省くショートカットのようなものです。
Action とその Binding の 両方 に Interaction が適用される場合は、各 Binding の Interaction のリストの末尾に、Action の Interaction を 付加 した場合と同じ結果になります。つまり、Binding の Interaction が 最初 に適用され、Action の Interaction がその 後 に適用されます。
Input Action Asset エディターウィンドウ内の Action には、Binding の場合と 同じ方法 で Interaction を加えて編集できます。編集する Action を選択し、ウィンドウの右ペインで Interaction を設定します。
コードで Action を作成する場合は、以下のように Interaction を指定できます。
var Action = new InputAction(Interactions: "tap(duration=0.8)");
定義済みの Interaction
Input System パッケージには、開発者が使用できる一連の基本的な Interaction が含まれています。Action に Interaction が設定されていない場合は、デフォルトの Interaction が使用されます。
ノート: ビルトイン Interaction では、Control の作動量に対して処理が行われ、Control の値が直接使用されることはありません。Input System では、Control の作動量に対して
pressPoint
パラメーターが評価されます。したがって、これらの Interaction は、ボタンで使用できるだけでなく、スティックなどの作動量を持つあらゆる Control で使用できます。
以下の図は、単純なボタン押下に対するビルトイン Interaction の動作を示しています。
デフォルトの Interaction
Binding またはその Action に特に Interaction を設定していない場合は、デフォルトの Interaction が Binding に適用されます。
Value
タイプの Action の動作は、以下のとおりです。
- バインドされた Control が 作動 すると、Action は即座に
Waiting
からStarted
に、その直後にPerformed
になり、Started
に戻ります。InputAction.started
コールバックが 1 回呼び出され、続いてInputAction.performed
コールバックが 1 回呼び出されます。 - バインドされた Control が作動し続けている間、Action は
Started
のまま維持され、Control の値が変更されるたびにPerformed
がトリガーされます (このとき、InputAction.performed
が 1 回呼び出されます)。 - バインドされた Control の作動が停止すると、Action は
Canceled
になってからWaiting
に戻ります。InputAction.canceled
が 1 回呼び出されます。
Button
タイプの Action の動作は、以下のとおりです。
- バインドされた Control が 作動 すると、Action は即座に
Waiting
からStarted
になります。InputAction.started
のコールバックが 1 回発生します。 - Control がボタン押下しきい値以上に達すると、Action は
Started
からPerformed
になります。InputAction.performed
のコールバックが 1 回発生します。ボタンの押下しきい値のデフォルト値は、入力設定 で定義されます。ただし、個々のコントロールでこの値を オーバーライド することもできます。 - Action が
Performed
になった後、すべての Control が 解放しきい値 以下の作動レベルに戻ると、Action はPerformed
からCanceled
になります。InputAction.canceled
が 1 回呼び出されます。 - Action が
Performed
にならなかった場合は、Control の解放と同時にCanceled
になります。InputAction.canceled
が 1 回呼び出されます。
PassThrough
タイプの Action の動作は、よりシンプルです。Input System では、バインドされた Control を単一の入力ソースとして追跡しようとするのではなく、値が変更されるたびに Performed
コールバックがトリガーされます。
コールバック | InputActionType.Value |
InputActionType.Button |
InputActionType.PassThrough |
---|---|---|---|
started |
Control の値がデフォルト値から変更されました。 | ボタンが押され始めましたが、まだ押下しきい値を超えたとは限りません。 | Action 後の、Control の最初の作動が有効になりました。 |
performed |
Control の値が変更されました。 | ボタンが、少なくともボタンの 押下しきい値 まで押されました。 | Control の値が変更されました。 |
canceled |
Control が作動状態ではなくなりました。 | ボタンが解放されました。ボタンが押下しきい値を超えて押されていた場合は、解放しきい値 以下まで放されました。ボタンが完全には押されていなかったとしても、現在は、まったく押されていない状態に戻りました。 | Action が無効になりました。 |
Press (押下)
PressInteraction
を使用すると、ボタンのような Interaction を明示的に強制できます。behavior
パラメーターを使用して、Interaction がボタンの押下、解放、その両方のどれをトリガーするかを選択します。
パラメーター | 型 | デフォルト値 |
---|---|---|
pressPoint |
float |
InputSettings.defaultButtonPressPoint |
behavior |
PressBehavior |
PressOnly |
コールバック/behavior |
PressOnly |
ReleaseOnly |
PressAndRelease |
---|---|---|---|
started |
Control の作動量が pressPoint を超えました。 |
Control の作動量が pressPoint を超えました。 |
Control の作動量が pressPoint を超えました。 |
performed |
Control の作動量が pressPoint を超えました。 |
Control の作動量が pressPoint 未満に戻りました。 |
- Control の作動量が pressPoint を超えました。または - Control の作動量が pressPoint 未満に戻りました。 |
canceled |
使用されません。 | 使用されません。 | 使用されません。 |
Hold (ホールド)
HoldInteraction
は、Input System によって Action がトリガーされる前にユーザーが Control を duration
秒間押し続けることを要求します。
パラメーター | 型 | デフォルト値 |
---|---|---|
duration |
float |
InputSettings.defaultHoldTime |
pressPoint |
float |
InputSettings.defaultButtonPressPoint |
コールバック | |
---|---|
started |
Control の作動量が pressPoint を超えました。 |
performed |
Control の作動量が、duration 秒以上の間、pressPoint を超えて維持されました。 |
canceled |
Control の作動量が、duration 秒の経過前に pressPoint 未満に戻りました (つまり、ボタンが押されていた時間が短すぎます)。 |
Tap (タップ)
TapInteraction
は、Action をトリガーする操作として、ユーザーが Control を押して duration
秒以内に放すことを要求します。
パラメーター | 型 | デフォルト値 |
---|---|---|
duration |
float |
InputSettings.defaultTapTime |
pressPoint |
float |
InputSettings.defaultButtonPressPoint |
コールバック | |
---|---|
started |
Control の作動量が pressPoint を超えました。 |
performed |
Control の作動量が、duration 秒の経過前に pressPoint 未満に戻りました。 |
canceled |
Control の作動量が、duration 秒以上 pressPoint を超えて維持されました (つまり、タップの時間が長すぎました)。 |
SlowTap (長押しタップ)
SlowTapInteraction
は、Action をトリガーする操作として、ユーザーが Control を duration
秒以上押し続けてから放すことを要求します。
パラメーター | 型 | デフォルト値 |
---|---|---|
duration |
float |
InputSettings.defaultSlowTapTime |
pressPoint |
float |
InputSettings.defaultButtonPressPoint |
コールバック | |
---|---|
started |
Control の作動量が pressPoint を超えました。 |
performed |
Control の作動量が、duration 秒の経過後に pressPoint 未満に戻りました。 |
canceled |
Control の作動量が、duration 秒の経過前に pressPoint 未満に戻りました (つまり、タップの時間が短すぎました)。 |
MultiTap (マルチタップ)
MultiTapInteraction
は、この Interaction をトリガーする操作として、ユーザーが Control を押して tapTime
秒以内に放し、それを tapDelay
秒以内の間隔で tapCount
回繰り返すことを要求します。これを使用して、ダブルクリックジェスチャやマルチクリックジェスチャを検出できます。
パラメーター | 型 | デフォルト値 |
---|---|---|
tapTime |
float |
InputSettings.defaultTapTime |
tapDelay |
float |
2 * tapTime |
tapCount |
int |
2 |
pressPoint |
float |
InputSettings.defaultButtonPressPoint |
コールバック | |
---|---|
started |
Control の作動量が pressPoint を超えました。 |
performed |
Control の作動量が pressPoint 未満に戻ってから再び超える動きが tapCount 回繰り返されました。 |
canceled |
- Control の作動量が pressPoint 未満に戻った後、tapDelay 秒以内に再び pressPoint を超えることがありませんでした (つまり、タップの間隔が長すぎました)。または - Control の作動量が再び pressPoint を超えた後、tapTime 秒以内に pressPoint 未満に戻りませんでした (つまり、タップの時間が長すぎました)。 |
カスタム Interaction の作成
カスタム Interaction を作成してプロジェクトで使用することもできます。カスタム Interaction は、UI とコードのどちらでも、ビルトインの Interaction と同様に使用できます。以下のように、IInputInteraction
インターフェースを実装するクラスを作成します。
// 軸を一方の端から反対の端まですばやく動かしたときに
// 実行される Interaction。
public class MyWiggleInteraction : IInputInteraction
{
public float duration = 0.2;
void Process(ref InputInteractionContext context)
{
if (context.timerHasExpired)
{
context.Canceled();
return;
}
switch (context.phase)
{
case InputActionPhase.Waiting:
if (context.Control.ReadValue<float>() == 1)
{
context.Started();
context.SetTimeout(duration);
}
break;
case InputActionPhase.Started:
if (context.Control.ReadValue<float>() == -1)
context.Performed();
break;
}
}
// プロセッサーとは異なり、Interaction はステートフルにすることができます。つまり、
// 入力を受け取るにつれ、時間と共に変化するローカルの状態を保持できます。システムで、
// 特定の時点で Reset() メソッドが呼び出されて、ローカルの状態へのリセットを Interaction が
// 求められることがあります。
void Reset()
{
}
}
次に、作成した Interaction を Input System に登録する必要があります。以下のメソッドを初期化コードで呼び出します。
InputSystem.RegisterInteraction<MyWiggleInteraction>();
これで、新しい Interaction が Input Action Asset エディターウィンドウ で使用可能になります。以下のように、コードで Interaction を指定することもできます。
var Action = new InputAction(Interactions: "MyWiggle(duration=0.5)");