控制器、手柄和摇杆

Godot supports hundreds of controller models thanks to the community-sourced SDL game controller database.

控制器支持Windows、macOS、Linux、Android、iOS和HTML5。

Note that more specialized devices such as steering wheels, rudder pedals and HOTAS are less tested and may not always work as expected. If you have access to one of those devices, don't hesitate to report bugs on GitHub.

在本指南中,您将学会:

  • 如何编写你的输入逻辑,从而支持键盘和控制器输入。

  • 控制器的行为如何与键盘/鼠标输入不同。

  • 解决 Godot 中控制器的问题。

支持通用导出

得益于 Godot 的输入动作系统,Godot 可以同时支持键盘和控制器输入,而不需要编写单独的代码路径。你不应该在脚本中对控制器的按键进行硬编码,应该在项目设置中创建输入动作,这些动作引用按键和控制器输入。

输入动作在 使用 InputEvent 页面上有详细解释。

备注

与键盘输入不同,支持鼠标和控制器输入的动作将需要不同的代码路径,例如在第一人称游戏中四处查看,因为这些必须被分开处理。

我应该使用哪个输入单例方法?

有3种方式可以以模拟感知的方式获得输入:

  • 当你有两个轴,如操纵杆或WASD运动,并希望两个轴都表现为单一输入时,使用 Input.get_vector() :

# `velocity` will be a Vector2 between `Vector2(-1.0, -1.0)` and `Vector2(1.0, 1.0)`.
# This handles deadzone in a correct way for most use cases.
# The resulting deadzone will have a circular shape as it generally should.
var velocity = Input.get_vector("move_left", "move_right", "move_forward", "move_back")

# The line below is similar to `get_vector()`, except that it handles
# the deadzone in a less optimal way. The resulting deadzone will have
# a square-ish shape when it should ideally have a circular shape.
var velocity = Vector2(Input.get_action_strength("move_right") - Input.get_action_strength("move_left"),
            Input.get_action_strength("move_back") - Input.get_action_strength("move_forward")).clamped(1)
  • 当你有一个轴可以双向移动时,比如飞行操纵杆上的油门,或者你想单独处理不同的轴时,使用 Input.get_axis() :

# `walk` will be a floating-point number between `-1.0` and `1.0`.
var walk = Input.get_axis("move_left", "move_right")

# The line above is a shorter form of:
var walk = Input.get_action_strength("move_right") - Input.get_action_strength("move_left")
  • 对于其他类型的模拟输入,例如处理一个触发器或一次处理一个方向,使用 Input.get_action_strength() :

# `strength` will be a floating-point number between `0.0` and `1.0`.
var strength = Input.get_action_strength("accelerate")

对于非模拟数字/布尔输入(只有 "按下 " 或 "未按下 " 的值),如控制器按钮、鼠标按钮或键盘按键,使用 Input.is_action_pressed() :

# `jumping` will be a boolean with a value of `true` or `false`.
var jumping = Input.is_action_pressed("jump")
// `jumping` will be a boolean with a value of `true` or `false`.
bool jumping = Input.IsActionPressed("jump");

在3.4之前的Godot版本,如3.3, Input.get_vector()Input.get_axis() 不可用。只有 Input.get_action_strength()Input.is_action_pressed() 在Godot 3.3中可用。

键盘/鼠标和控制器输入之间的差异

如果您习惯于处理键盘和鼠标输入,可能会对控制器处理特定情况的方式感到惊讶。

死区

与键盘和鼠标不同,控制器提供带有模拟输入的轴。模拟输入的好处是它们为动作提供了额外的灵活性。不像数字输入只能提供 0.01.0 的强度,模拟输入可以提供 0.01.0 之间的任何强度。缺点是没有死区系统,由于控制器的物理结构,模拟轴的强度永远不会等于 0.0。相反,它将徘徊在一个低值,如 0.062。这种现象被称为漂移,在旧的或有问题的控制器上会更加明显。

让我们把赛车游戏作为一个现实世界的例子。由于有了模拟输入,我们可以将汽车慢慢地转向一个或另一个方向。然而,如果没有死区系统,即使玩家不接触操纵杆,汽车也会自己慢慢转向。这是因为方向轴的强度在我们期望的时候不会等于 0.0。因为我们不希望我们的车在这种情况下自动转向,我们定义了一个“死区”值 0.2,它将忽略所有强度低于 0.2 的输入。一个理想的死区值是足够高的,可以忽略操纵杆漂移引起的输入,但又足够低,不会忽略玩家的实际输入。

Godot 有一个内置的死区系统来解决这个问题。默认值是 0.2,但你可以在“项目设置”的“按键映射”选项卡中根据每个动作增加或减少它。对于 Input.get_vector(),可以指定死区,否则它将从向量中的所有动作计算出平均死区值。

“回声”事件

与键盘输入不同,按住一个控制器按钮,如十字方向键,不会产生固定间隔的重复输入事件(也被称为“回声”事件)。这是因为操作系统首先不会为控制器输入发送“回声”事件。

如果你想让控制器按钮发送回声事件,你将不得不通过代码生成 InputEvent 对象,并使用 Input.parse_input_event() 定期解析它们。这可以在 Timer 节点的帮助下完成。

故障排除

参见

你可以在 GitHub 上查看控制器支持的已知问题列表

Godot 无法识别我的控制器。

首先,检查你的控制器是否被其他应用程序识别。你可以使用 Gamepad Tester 网站来确认你的控制器被识别。

我的控制器的按钮或轴映射不正确。

If buttons are incorrectly mapped, this may be due to an erroneous mapping from the SDL game controller database. You can contribute an updated mapping to be included in the next Godot version by opening a pull request on the linked repository.

有很多方法来创建映射。一个选择是使用 官方Joypads演示 中的映射向导。一旦你有了控制器可工作的映射,你可以在运行Godot之前通过定义 SDL_GAMECONTROLLERCONFIG 环境变量来测试它:

export SDL_GAMECONTROLLERCONFIG="your:mapping:here"
./path/to/godot.x86_64

要在非桌面平台上测试映射,或者用额外的控制器映射来分发你的项目,你可以通过调用 Input.add_joy_mapping() 尽早在脚本的 _ready() 函数中添加它们。

我的控制器在特定的平台上工作,但在另一个平台上却不能。

macOS

控制器目前只支持基于 x86 的 Mac 电脑。这意味着控制器不能在采用 ARM 处理器的 Mac 上工作,如苹果 M1。

Linux

在 Godot 3.3 之前,官方的 Godot 可执行文件在编译时支持 udev,但自编译的可执行文件在编译时不支持 udev,除非在 SCons 命令行中传递 udev=yes。这使得控制器的热插拔支持在自编译的可执行文件中不可用。

HTML5

与 "本地" 平台相比,HTML5 控制器的支持通常不太可靠。各个浏览器对控制器的支持质量往往相差甚远。因此,如果玩家无法使用他们的控制器,你可能不得不指示他们使用不同的浏览器。

Also, note that controller support was significantly improved in Godot 3.3 and later.