うどんてっくメモ

技術的なメモをまったりと

【Unity】新しいInputSystemのInputStateHistoryを使って入力情報を記録する

はじめに

本記事では新しいInputSystemの機能の説明や、導入手順などは省略します。
検証しているツールとパッケージのバージョンは以下の通りです。

  • Unity 2021.1.3f1
  • Input System 1.0.2

バージョンによっては挙動が違うことがありますので、ご注意ください。

InputStateHistoryの使い方

新しいInputSystemにおけるInputControlの記録を行うための機能です。 InputControlについてはこちらのドキュメントを参照してください。
Controls | Input System | 1.0.2

簡単なサンプルをまず示します。

// 生成
var history = new InputStateHistory(Mouse.current.leftButton);

// 記録開始
history.StartRecording();

// 何かしらするとして

// 記録終了
history.StopRecording();

foreach (var record in history)
{
     Debug.Log(record.ReadValue<float>());
}

history.Dispose();

Mouse.current.leftButtonはマウスの左クリックのInputControlです。記録するInputControlを元にInputStateHistoryを生成し、StartとStopを呼ぶというシンプルな使い方です。
InputStateHistory自体はRecordという記録対象のInputControlに加え、時間や前後のInputControlを参照できるstructのIEnumerableとなっています。
Mouse.current.leftButtonはクリックしてなければ0、クリックしたら1を返すInputControlです。なので、上のサンプルでは0と1という入力の値の履歴を取得することができます。

InputStateHistoryのコンストラクタに渡すのは、記録対象となるControlです。 Mouse、GamePad、JoyStick、TouchScreenといった異なる入力インターフェイスについても、InputControlを実装しているものについては記録対象とすることが可能です。

// クリックしたかどうかを取るButtonControl
var mouse_history_is_click = new InputStateHistory(Mouse.current.leftButton);

// 移動量を取るVector2Control
var mouse_history_position = new InputStateHistory(Mouse.current.delta);

// クリック回数を取るIntegerControl
var mouse_history_click_count = new InputStateHistory(Mouse.current.clickCount);

// タッチ情報をとるTouchControl
var touch_history = new InputStateHistory(TouchScreen.current.primaryTouch);

// GamePadのAボタンを取るButtonControl
var gamepad_history = new InputStateHistory(Gamepad.current.aButton);

コンストラクタには具体的なInputControlだけでなく、パスでの指定も可能です。InputControlのパスの表現についても前述のドキュメントに詳しく書いてあります。
このように任意のInputControlについてよしなに記録を行えるのがInputStateHistoryの機能となります。

開始と終了を宣言するだけではなく、入力を記録したときに処理を挟むことも可能です。

// イベントの登録
history.onRecordAdded += record => Debug.Log(record.ReadValue<float>());

InputControlについてはそのControl自体を知りたいという場合は少なく、たとえばボタンであればクリックしたかどうか、カーソルであれば位置など、大抵はControlが観測する値についてだけ関心がある場合が多いです。 その場合はジェネリクス付きのInputStateHistroyを活用することでシンプルに値を取得可能です。

var history = new InputStateHistory<Vector2>(Touchscreen.current.position);
history.StartRecording();

// 何かしらの処理

history.StopRecording();

foreach (var record in history)
{
     // Vector2が返ってくる
     Debug.Log(record.ReadValue());
}

history.Dispose();

また、入力情報が多すぎるので直近のデータが一定数だけ欲しいという場合にはhistoryDepthを指定することで実現できます。

var history = new InputStateHistory<Vector2>(Gamepad.current.leftStick);
history.historyDepth = 100;
history.StartRecording();

終わりに

入力履歴をデータ化することで、たとえば特定の事象を引き起こす操作の再現や、検証ルーチンの自動化などさまざまな活用が期待できます。 ここで紹介したInputStateHistoryの他にも入力情報を可視化するVisualizerやTestなど、検証に有効な機能が色々と用意されています。 InputSystemの機能を活用して実装の改善だけでなく、開発の効率化にも目を向けていきたいです。