ジョイスティックで操作する (入力システムパッケージ版)
現在表示しているページは選択中の表示言語には対応しておりません。
検証環境
- Windows
-
- Windows 11
- Unity エディター
-
- 2020.3.25f1
- 入力システムパッケージ
-
- 1.2.0
この Tips の前提設定
この Tips の説明の前提として以下の設定を事前に行っています。
XInput と DirectInput について
Windows 限定の話になりますが、ゲームコントローラーの接続形式として「DirectInput」と「XInput」というものがあります。 ここでの「ジョイスティック」は「DirectInput」に該当します。
今回のプログラムでは Joystick
クラスを扱っていますがこれは「DirectInput」に対応したコントローラーしか扱うことができません。
「XInput」に対応したコントローラーを使うには別の Gamepad
クラスを使う必要があります。
「DirectInput」は古くからある接続形式でボタンの定義などが割とあいまいになっており特殊な形状のコントローラーなどを扱うことができます。 しかし最近は「XInput」が主流になっていることもあり「DirectInput」に対応していないコントローラーも増えてきています。 「DirectInput」はボタンの定義が「1」「2」「3」という風になっているのでゲーム制作者はゲームとコントローラーのボタン対応を適切に設定できるように作らなければなりません。
「XInput」は「DirectInput」の次世代として定義されたもので A ボタンや B ボタン、トリガー、スティックなどあらかじめ定義されています。 そのためコントローラーの形状はほぼ決まったものしか使えませんが、 ボタンなどの定義がきちんと決まっているのでゲーム制作者はボタンの配置などを気にせずにコントローラーに合ったゲームを作ることができます。 最近のゲームコントローラーでは「XInput」のみに対応しているものも増えてきています。
ジョイスティックについて
前述のとおりボタンの定義などがないため、実際に使用するには各ボタンの情報を調べながらゲームの操作を割り当てるというような面倒な処理を入れる必要があります。 DirectInput は古いので新しいゲームで採用する必要はないと思いますが、どうしても対応させたい場合はプログラムが複雑になる可能性があることに注意してください。
今回のサンプルも基本的に列挙したボタンの情報を取得するだけにとどめています。
実際には name
などを確認して操作を割り当てる必要があります。
ジョイスティックの情報取得
ジョイスティックの各ボタンの情報を表示させるためのテキストオブジェクトを配置します。
スクリプトを作成します。名前は任意ですがここでは JoystickInfo
とします。
スクリプトは以下のようにします。 コントローラーの種類によって得られる情報がまちまちであり、 各コントローラーに合わせてプログラムを入れるのは非常に困難なので全てのボタンを列挙してボタンの種類と押下情報を取得するだけにしています。
using System.Text;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.UI;
public class JoystickInfo : MonoBehaviour
{
<summary>情報を表示させるテキストオブジェクト。</summary>
[SerializeField] private Text TextObject;
StringBuilder Builder = new StringBuilder();
// 更新はフレームごとに1回呼び出されます
void Update()
{
if (TextObject == null)
{
Debug.Log($"{nameof(TextObject)} が null です。");
return;
}
// 1つ目のジョイスティックの情報を取得
var joystick = Joystick.current;
if (joystick == null)
{
Debug.Log("ジョイスティックがありません。");
TextObject.text = "";
return;
}
Builder.Clear();
// ジョイスティックの情報取得
Builder.AppendLine($"deviceId:{joystick.deviceId}");
Builder.AppendLine($"name:{joystick.name}");
Builder.AppendLine($"displayName:{joystick.displayName}");
// ジョイスティックにはボタンの大部分が定義されていないので
// 基本的には allControls で列挙して入力の種類と値を確認していく
foreach (var key in joystick.allControls)
{
if (key is StickControl stick)
{
if (stick.up.isPressed) Builder.AppendLine($"{key.name} Up");
if (stick.down.isPressed) Builder.AppendLine($"{key.name} Down");
if (stick.left.isPressed) Builder.AppendLine($"{key.name} Left");
if (stick.right.isPressed) Builder.AppendLine($"{key.name} Right");
var value = stick.ReadValue();
if (value.magnitude > 0f)
{
Builder.AppendLine($"{key.name}:{value.normalized * value.magnitude}");
}
}
else if (key is Vector2Control vec2)
{
var value = vec2.ReadValue();
if (value.magnitude > 0f)
{
Builder.AppendLine($"{key.name}:{value.normalized * value.magnitude}");
}
if (vec2.x.ReadValue() != 0f)
{
Builder.AppendLine($"{key.name}.x:{vec2.x.ReadValue()}");
}
if (vec2.y.ReadValue() != 0f)
{
Builder.AppendLine($"{key.name}.x:{vec2.y.ReadValue()}");
}
}
else if (key is ButtonControl button)
{
if (button.isPressed) Builder.AppendLine($"{key.name} isPress");
var value = button.ReadValue();
if (value != 0f)
{
Builder.AppendLine($"{key.name}:{value}");
}
}
else if (key is AxisControl axis)
{
if (axis.IsPressed()) Builder.AppendLine($"{key.name} isPress");
var value = axis.ReadValue();
if (value != 0f)
{
Builder.AppendLine($"{key.name}:{value}");
}
}
else
{
Builder.AppendLine($"Type={key.GetType()}");
}
}
// 押しているボタン一覧をテキストで表示
TextObject.text = Builder.ToString();
}
}
接続されているジョイスティックの情報は Joystick.current
で取得できます。
あとは Joystick
クラスから各情報を取得する形になります。
Joystick
クラスを見ると分かりますが、一応 stick
や trigger
などの定義はありますが A ボタンやスタートボタンなどの定義はありません。
そのため、allControls
プロパティを使用してすべてのボタン、スティックを列挙してボタンの種類と押下情報を調べる必要があります。
スクリプトを保存したら EventSystem
にアタッチして情報表示用のテキストオブジェクトをセットします。
ゲームを動かして DirectInput に対応したコントローラーで動かしてみてください。各情報を取得することができます。
コントローラーにもよりますが、スティックや方向キーなどを押したときに意図したような形で値が取得できない場合があります。 このようにボタンが定義されていないため各ボタンの正確な押下情報の取得が難しく、 さらにコントローラーによってボタンの配置が異なっていたりとジョイスティックに完全に対応するのはなかなか困難であることが分かります。
もしゲームをジョイスティックに対応させるならキーコンフィグのような設定画面を用意して各ユーザーが持っているコントローラーのボタン配置をカスタマイズできるようにするのが望ましいかと思います。
複数のジョイスティックの情報を取得する方法
接続されている全てのジョイスティックの情報は Joystick.all
で取得することができます。
ReadOnlyArray
で定義されているので foreach
などで列挙することができます。
各値は Joystick
クラスなので前述のプログラムと同様にジョイスティックの情報を取得することができます。