[Unity][Input System]キーボード&マウスとコントローラー操作の両立で詰まった


困った内容

①一人のキャラクターに対する複数デバイスのペアリングが分からなかった
②ControlSchemeのAutoSwitchが効いていない様な挙動に出会った

今回のケースの解決策

①pairWithDevice(もしくはpairWithDevices)は指定不要
②下図のチェックボックスがオンになっているとダメだった

②の原因として、PlayerInputManager.joiningEnabledがtrueの場合、PlayerInput.isSinglePlayerが有効にならないようだ。
(PlayerInput.csの814行目)
Auto SwitchはSinglePlayerモードの時のみ利用できる機能なので、いけなかったわけである。

ではなぜjoiningEnabledがtrueだとisSinglePlayerが無効になるのか。
恐らくだが、Join Playerのオプションにある
「アクティブでないデバイスのボタンが押されたら、自動で追加のプレイヤー(2P等)を生成する」に関連していると思われる。
Auto Switchの挙動と新規プレイヤーの参戦は、どちらも
「現在使用していないデバイスで入力が行われる」がトリガーである為、
参戦可能状態を切っておかなければ、1Pに心置きなくデバイスを
触らせてあげる事が出来ないのではないか。
と思った。

どれだけ調べてもどこにも載っていないので、念の為残しておく。
デフォルトでチェック付いてるし印象も薄いし強烈に関連付いてるって感じでもないのに記事が無いって事は誰もハマってないのだろうか・・・。
本件の解決に結構な時間を割いたので、怒りの初投稿である。


そもそもなぜこの様な問題に直面する事になったのか

現在開発中のものはソロとローカルマルチプレイを想定したゲームで、
基本的にはゲームパッドでの操作を想定しているが、キーボードマウスなどでも操作できるに越した事はないだろうと考えている。
恐らくマルチプレイ時にはどのデバイスを誰が使用するのか
「ペアリング」する画面が(未来の自分によって)作られると思うが、
ソロの場合は接続されているどのデバイスでも動いたらええんちゃうかと思った。
(キーボード壊れて変な入力値入っちゃうとかあり得るので、ソロでもペアリングは選べた方が良いと思う)

ここからはほぼ「困った内容①」の詳細になってしまう。
私はJoin Player Manuallyの設定で実装しているので、
PlayerInputManager.instance.JoinPlayerを使用しているが、
このメソッドの引数pairWithDevicesInputSystem.devicesで取ってきたデバイス(キーボード、マウス、コントローラー)をToArrayして全部突っ込んだら全部ペアリングされて、それがAuto Switchされると思った。
だがPlayerInputManagerやらでInstantiateされて返ってくるはずのPlayerInput自体がそもそもnullで返ってくる。

Breakして処理の中に入っていくと、

PlayerInputManager.JoinPlayer
     ↓
PlayerInput.Instantiate
     ↓
PlayerInput.DoInstantiate
     ↓ (今日の時点では)1101行目のObject.Instantiate(prefab)の直後に
PlayerInput.OnEnable
     ↓ 色々呼ばれるが問題の箇所だけ
PlayerInput.AssignUserAndDevices
     ↓
PlayerInput.TryToActivateControlScheme

の1544行目あたりで
foreach (device in pairWithDeviceたち)
 if (!controlScheme.SupportsDevice(device))
  return false; // 1個でもSchemeに合わないの渡したら怒られる

これがFalseになるせいでこのプレイヤーはダメだといわれnullが返される。
この厳しすぎるチェック体制が原因にあった。
pairWithDevice(s)によるデバイスの指定を行う場合は、対象のcontrolSchemeと完全に一致したデバイスのみを指定しなければならないようだ。
ちなみにデバイスを指定せずにSchemeのみ指定した場合はどのデバイスでも動いた。
Schemeを指定しなかった場合、上に記載した処理フローの中で自動で(恐らくInputActionAsset等で一番上のSchemeに)指定される。
今回のケースではキーボード&マウスが指定されているのだが、一緒にpairWithDeviceしてあるコントローラーがcontrolScheme: キーボードマウスに該当しない為、プレイヤーの生成が中断されてしまっていた。
該当しないデバイスがあっても見逃してくれるたら良いのにというのが正直な気持ちではあるが、なぜこのケースのみ厳格なチェックを行うのだろうか。
その背景を考えてみた。

考えられる理由としては、マルチプレイ時に意図しないデバイスで意図しないキャラクターが操作できてしまう事件を防ぐためであろうか。
そもそもSchemeのAuto SwitchはPlayerInput.isSinglePlayerがtrueの時のみ動作する。
恐らくUnity的には、わざわざpairWithしてきたって事は確実にこのデバイスのみで動いてほしいんだなと解釈し、Schemeにそぐわないデバイスがある場合は異常事態であると、そう判断されるのではないだろうか。


調べてもほとんど出てこないという事で、誰もこんな所で行き詰らないかもしれないが、誰かの何かになればと思う。


この記事が気に入ったらサポートをしてみませんか?