使用游戏手柄进行控制(输入系统包版本)

更新页 :
页面创建日期 :

验证环境

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

此提示的先决条件

作为此提示描述的前提,已预先进行了以下设置。

关于 XInput 和 DirectInput

虽然它仅限于Windows,但游戏控制器有两种连接格式:DirectInput和XInput。 在这里,“游戏手柄”对应于“XInput”。

该程序 Gamepad 处理类,但这只能处理支持“XInput”的控制器。 若要使用支持 DirectInput 的控制器,需要使用不同的 Joystick 类。

“DirectInput”是一种旧的连接格式,按钮的定义相对模糊,它可以处理具有特殊形状的控制器。 然而,最近,“XInput”已经成为主流,不支持“DirectInput”的控制器数量正在增加。 “DirectInput”具有“1”、“2”和“3”等按钮定义,因此游戏创建者必须在游戏和控制器之间创建按钮对应关系,以便可以正确设置它们。

XInput 被定义为下一代 DirectInput,包括预定义的 A 和 B 按钮、触发器、摇杆等。 因此,只能使用固定形状的控制器, 由于按钮的定义很好,游戏创建者可以创建适合控制器的游戏,而无需担心按钮的位置。 最近仅支持“XInput”的游戏控制器正在增加。

确定是否按下了按钮

您可以确定是否通过属性以及 xxxxxxxx.isPressed 键盘和鼠标按下按钮。 在这里,我想在文本中显示我按下的按钮类型。

首先,放置一个显示文本对象。

为判决创建脚本。 文件名是任意的,但这里是 GamepadButtons .

脚本如下所示:

using System.Text;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.UI;

public class GamepadButtons : 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 gamepad = Gamepad.current;
    if (gamepad == null)
    {
      Debug.Log("ゲームパッドがありません。");
      TextObject.text = "";
      return;
    }

    Builder.Clear();

    // ボタンを押している間は xxxxxxxx.isPressed が true を返します

    // B ボタンや East ボタン、○ボタンは読み方が違うだけで同じボタンです
    // これは PlayStation や Xbox, Switch などでボタンの読み方が違うためです
    if (gamepad.aButton.isPressed) Builder.AppendLine($"A");
    if (gamepad.bButton.isPressed) Builder.AppendLine($"B");
    if (gamepad.xButton.isPressed) Builder.AppendLine($"X");
    if (gamepad.yButton.isPressed) Builder.AppendLine($"Y");

    if (gamepad.buttonEast.isPressed) Builder.AppendLine($"East");
    if (gamepad.buttonWest.isPressed) Builder.AppendLine($"West");
    if (gamepad.buttonNorth.isPressed) Builder.AppendLine($"North");
    if (gamepad.buttonSouth.isPressed) Builder.AppendLine($"South");

    if (gamepad.circleButton.isPressed) Builder.AppendLine($"Circle");
    if (gamepad.crossButton.isPressed) Builder.AppendLine($"Cross");
    if (gamepad.triangleButton.isPressed) Builder.AppendLine($"Triangle");
    if (gamepad.squareButton.isPressed) Builder.AppendLine($"Square");

    // コントローラーの中央にあるスタートボタン、セレクトボタン、メニューボタン、ビューボタンなどに該当します。
    if (gamepad.startButton.isPressed) Builder.AppendLine($"Start");
    if (gamepad.selectButton.isPressed) Builder.AppendLine($"Select");

    // 左と右のスティックをまっすぐ押し込んだかどうかを判定します
    if (gamepad.leftStickButton.isPressed) Builder.AppendLine($"LeftStickButton");
    if (gamepad.rightStickButton.isPressed) Builder.AppendLine($"RightStickButton");

    // 左上と右上にあるボタン。PlayStation だと L1 や R1 に該当します
    if (gamepad.leftShoulder.isPressed) Builder.AppendLine($"LeftShoulder");
    if (gamepad.rightShoulder.isPressed) Builder.AppendLine($"RightShoulder");

    // 押しているボタン一覧をテキストで表示
    TextObject.text = Builder.ToString();
  }
}

保存脚本后 EventSystem ,将其附加到显示文本对象并对其进行配置。

尝试运行游戏,看看每个按钮是否响应。

顺便说一下,以下按钮被定义为同一个按钮,尽管准备了多个按钮,因为它们的读取方式因游戏机而异。 在上述每个程序中,都包含一个判断过程,因此当您按下按钮时,会显示三个按钮。

XboxPlayStation
b按钮 圆圈按钮 按钮东
a按钮 十字按钮 按钮南
x按钮 方形按钮 纽扣西
y按钮 三角形按钮 按钮北

可以判断为按钮的内容如下。

  • 按钮、×按钮、向下按钮
  • B 按钮、○ 按钮、右按钮
  • X 按钮、□按钮、左按钮
  • Y 按钮、向下箭头按钮、向上按钮
  • “开始”按钮、“菜单”按钮
  • “选择”按钮、“查看”按钮
  • 左肩按钮,L1按钮
  • 右肩按钮,R1按钮
  • 左摇杆按钮
  • 右摇杆按钮

确定是否按下按钮

按下时的判断可以由键盘和鼠标的属性 xxxxxxxx.wasPressedThisFrame 决定。 返回按下该时刻的值,即使此后按下并按住该值 truefalse 返回。

让我们将按下的按钮显示为文本作为操作检查。 放置要显示的文本对象。

脚本的文件名可以是任何内容,但这里是 GamepadButtonsOneFrame .

脚本如下所示: 为简单起见,仅判断 4 个按钮。

using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.UI;

public class GamepadButtonsOneFrame : MonoBehaviour
{
  /// <summary>情報を表示させるテキストオブジェクト。</summary>
  [SerializeField] private Text TextObject;

  // 更新はフレームごとに1回呼び出されます
  void Update()
  {
    if (TextObject == null)
    {
      Debug.Log($"{nameof(TextObject)} が null です。");
      return;
    }

    // 1つ目のゲームパッドの情報を取得
    var gamepad = Gamepad.current;
    if (gamepad == null)
    {
      Debug.Log("ゲームパッドがありません。");
      TextObject.text = "";
      return;
    }

    // ボタンが押された瞬間かどうかを判定
    if (gamepad.aButton.wasPressedThisFrame) TextObject.text += "A";
    if (gamepad.bButton.wasPressedThisFrame) TextObject.text += "B";
    if (gamepad.xButton.wasPressedThisFrame) TextObject.text += "X";
    if (gamepad.yButton.wasPressedThisFrame) TextObject.text += "Y";
  }
}

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

尝试运行游戏并按下按钮。 我认为您按下的按钮将被添加。 您还可以看到按住按钮不会添加任何文本。

确定按钮是否松开的那一刻

没有示例,但你可以通过使用属性而不是wasReleasedThisFrame属性来确定是否是wasPressedThisFrame释放它的时刻。

确定何时按箭头键

确定 DPAD 的按下时间。 根据游戏机的不同,它将与箭头键和方向键一起飞行,但两者都被视为相同。 DPAD基本上只决定你是否朝着那个方向推动。 没有像棍子一样“推一点”这样的判断。

放置文本对象以显示是否按下该对象作为操作检查的决定。

创建脚本。 文件名是任意的,但这里是 GamepadDpad .

脚本如下所示:

using System.Text;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.UI;

public class GamepadDpad : 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 gamepad = Gamepad.current;
    if (gamepad == null)
    {
      Debug.Log("ゲームパッドがありません。");
      TextObject.text = "";
      return;
    }

    Builder.Clear();

    // Dpad の押下情報を Vector2 として取得するパターン
    var value = gamepad.dpad.ReadValue();
    Builder.Append($"(x:{value.x}, y:{value.y})");

    // Dpad の各方向のボタンを押しているかどうかの判定
    if (gamepad.dpad.left.isPressed) Builder.Append(" left");
    if (gamepad.dpad.right.isPressed) Builder.Append(" right");
    if (gamepad.dpad.up.isPressed) Builder.Append(" up");
    if (gamepad.dpad.down.isPressed) Builder.Append(" down");

    // Dpad の情報をテキストで表示
    TextObject.text = Builder.ToString();
  }
}

您可以在 上获取 DPAD 信息 Gamepad.dpad

DPAD 具有leftupdownright每个方向的属性,您可以确定它是否被属性等按下。 isPressed

DpadControl.ReadValue您还可以使用该方法在 中获取压力机的状态Vector2。 如果不按任何内容 (0, 0),如果按左键 (-1, 0),依此类推。

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

尝试运行游戏并与 DPAD 交互。

Vector2顺便说一下,处于规范化状态,因此当您对角线按下时,它以数字形式获得,例如 (0.7071, 0.7071) 而不是 (1, 1)。

确定触发按下

Xbox 控制器的左侧和右侧都有称为触发器的按钮。 在PlayStation上,它对应于L2R2。 此按钮与普通按钮不同,您可以在0.0~1.0中获取您按下的量。 其他一些控制器配备了触发器以外的名称,但在较旧的控制器等中,它们可能只是作为按钮放置,在这种情况下,按下的判断仅作为 0、1 处理。

在这里,我想检查扳机按下的次数。 放置要在画布上显示的文本对象。

创建脚本。 由于它将在其他地方使用,因此我们将在此处 GamepadReadValue 命名 。

脚本如下所示:

using System.Text;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.UI;

public class GamepadReadValue : 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 gamepad = Gamepad.current;
    if (gamepad == null)
    {
      Debug.Log("ゲームパッドがありません。");
      TextObject.text = "";
      return;
    }

    Builder.Clear();

    // トリガーの押下量を取得
    Builder.AppendLine($"LeftTrigger:{gamepad.leftTrigger.ReadValue()}");
    Builder.AppendLine($"RightTrigger:{gamepad.rightTrigger.ReadValue()}");

    // 情報をテキストで表示
    TextObject.text = Builder.ToString();
  }
}

Gamepad每个leftTrigger类都有一个属性,rightTriggerReadValue你可以通过调用该方法得到 0.0~1.0 范围内的按压量。 触发器也可以被视为按钮,因此isPressed您也可以判断诸如。 isPressed true顺便说一下,成为ReadValue的数量是基于 0.5。

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

尝试运行游戏并移动扳机。

确定摇杆信息

摇杆可以分别获取左摇杆和右摇杆的信息,并且可以得到摇杆在哪个方向向下推多少的量。 当然,如果您的控制器上没有摇杆,您将无法获得此信息。

棍子信息可以分别Gamepad.leftStick使用 检索。 Gamepad.rightStick

对于操作确认脚本,我们将转移之前用于获取触发器的脚本。

// 省略

public class GamepadReadValue : MonoBehaviour
{
  // 省略

  // 更新はフレームごとに1回呼び出されます
  void Update()
  {
    // 省略

    // トリガーの押下量を取得
    Builder.AppendLine($"LeftTrigger:{gamepad.leftTrigger.ReadValue()}");
    Builder.AppendLine($"RightTrigger:{gamepad.rightTrigger.ReadValue()}");

    // スティックの入力を取得
    var leftStickValue = gamepad.leftStick.ReadValue();
    Builder.AppendLine($"LeftStick:{leftStickValue.normalized * leftStickValue.magnitude}");
    var rightStickValue = gamepad.rightStick.ReadValue();
    Builder.AppendLine($"RightStick:{rightStickValue.normalized * rightStickValue.magnitude}");

    // 情報をテキストで表示
    TextObject.text = Builder.ToString();
  }
}

leftStickrightStick可以通过从 Vector2 或 调用ReadValue方法获取新闻信息。 Vector2因此,您可以获得在 X 轴和 Y 轴上按下了多少xy和属性, 如果你想得到你按下的方向,你可以在属性中得到它,如果你想magnitude得到你正在按下的数量,你可以在normalized属性中得到它。

尝试实际移动游戏并操作摇杆。

获取游戏手柄信息

您可以从连接的游戏手柄中获取ID,名称等。 例如,请参阅 以标识 name 所连接的控制器的类型,或 您可以参考连接多个游戏手柄时要与哪个 deviceId 游戏手柄关联。

在这里,我们将在文本中显示信息以检查操作。

脚本名称是任意的,但这里是 GamepadInfo .

脚本如下所示:

using System.Text;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.UI;

public class GamepadInfo : 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 gamepad = Gamepad.current;
    if (gamepad == null)
    {
      Debug.Log("ゲームパッドがありません。");
      TextObject.text = "";
      return;
    }

    Builder.Clear();

    // ゲームパッドの各情報を取得
    Builder.AppendLine($"deviceId:{gamepad.deviceId}");
    Builder.AppendLine($"name:{gamepad.name}");
    Builder.AppendLine($"displayName:{gamepad.displayName}");
    Builder.AppendLine($"shortDisplayName:{gamepad.shortDisplayName}");
    Builder.AppendLine($"path:{gamepad.path}");
    Builder.AppendLine($"layout:{gamepad.layout}");

    // 情報をテキストで表示
    TextObject.text = Builder.ToString();
  }
}

Gamepad您可以从检索到的. 以下是一些摘录。

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

尝试运行游戏以查看信息是否显示。