使用操纵杆操作(输入系统封装版本)

更新页 :
页面创建日期 :

验证环境

窗户
  • 窗户11
Unity 编辑器
  • 2020.3.25f1
输入系统包
  • 1.2.0

此提示的先决条件

以下设置已预先配置为解释这些提示的先决条件。

关于 XInput 和 DirectInput

虽然它仅限于 Windows,但游戏控制器有两种连接格式:“DirectInput”和“XInput”。 此处的“Joystick”对应于“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.currentJoystick 之后,我们将从班级中获取每个信息。

Joystick 从类中可以看出,有 和 等定义, stick trigger 但没有 A 按钮或开始按钮等定义。 因此,您应该使用“属性”来枚举所有按钮、摇杆,allControls 并找出按钮类型和新闻信息。

保存脚本后, EventSystem 将其附加到文本对象并设置用于显示信息的文本对象。

尝试使用支持 DirectInput 的控制器运行游戏。 可以检索每条信息。

根据控制器的不同,当您按下摇杆、箭头键等时,可能无法按预期获得值。 由于按钮不是以这种方式定义的,因此很难获得每个按钮的准确按下信息。 此外,您可以看到完全支持操纵杆非常困难,例如按钮的排列因控制器而异。

如果游戏要支持操纵杆,最好有一个像按键配置一样的设置屏幕,以便每个用户都可以自定义他们拥有的控制器的按钮布局。

如何获取多个操纵杆的信息

有关 Joystick.all 所有连接的操纵杆的信息,请参见 。 ReadOnlyArray 它可以 foreach 枚举在等中。

由于每个值都是一个 Joystick 类,因此您可以像在前面的程序中一样获取操纵杆信息。