Godot 游戏引擎 v4.3 输入事件处理教程
Godot 游戏引擎 v4.3 输入事件处理教程
在游戏开发中,处理玩家输入是至关重要的环节。Godot游戏引擎提供了强大的输入事件系统,支持键盘、鼠标、手柄等多种输入设备。本文将详细介绍如何在Godot 4.3版本中处理各种输入事件,包括事件轮询、输入映射、键盘事件、鼠标事件和触摸事件等。
事件和轮询
在处理玩家输入时,有两种主要方式:事件驱动和状态轮询。
- 事件驱动:使用
_input()
函数来响应特定的输入事件,如按键按下。 - 状态轮询:通过
Input
单例查询某个输入的状态,适用于需要持续检测的场景,如移动。
示例代码展示了如何在GDScript和C#中实现这两种方式:
func _input(event):
if event.is_action_pressed("jump"):
jump()
func _physics_process(delta):
if Input.is_action_pressed("move_right"):
position.x += speed * delta
public override void _Input(InputEvent @event)
{
if (@event.IsActionPressed("jump"))
{
Jump();
}
}
public override void _PhysicsProcess(double delta)
{
if (Input.IsActionPressed("move_right"))
{
position.X += speed * (float)delta;
}
}
输入事件
输入事件是继承自InputEvent
的对象,根据事件类型不同,对象会包含相关的属性。例如,按键事件会包含按键代码,鼠标事件会包含位置信息。
为了更好地理解输入事件,可以添加一个节点并附加以下脚本:
extends Node
func _input(event):
print(event.as_text())
using Godot;
public partial class Node : Godot.Node
{
public override void _Input(InputEvent @event)
{
GD.Print(@event.AsText());
}
}
运行后,你可以在输出窗口中看到每个输入事件的详细信息。
InputMap
InputMap
是处理各种输入的最灵活方式。你可以创建命名的输入动作,并将多个输入事件(如按键或鼠标点击)映射到同一个动作上。在项目设置中可以查看和添加自定义的输入动作。
一旦定义了动作,就可以在脚本中使用is_action_pressed()
和is_action_released()
来处理它们:
func _input(event):
if event.is_action_pressed("my_action"):
print("my_action occurred!")
public override void _Input(InputEvent @event)
{
if (@event.IsActionPressed("my_action"))
{
GD.Print("my_action occurred!");
}
}
键盘事件
键盘事件在InputEventKey
中被捕获。虽然建议使用输入动作来代替,但在某些情况下,你可能会想专门查看按键事件。例如,检查T键是否被按下:
func _input(event):
if event is InputEventKey and event.pressed:
if event.keycode == KEY_T:
print("T was pressed")
public override void _Input(InputEvent @event)
{
if (@event is InputEventKey keyEvent && keyEvent.Pressed)
{
if (keyEvent.Keycode == Key.T)
{
GD.Print("T was pressed");
}
}
}
键盘修饰键
修饰键属性继承自InputEventWithModifiers
,可以使用布尔属性检查修饰键的组合。例如,区分T键和Shift+T键:
func _input(event):
if event is InputEventKey and event.pressed:
if event.keycode == KEY_T:
if event.shift_pressed:
print("Shift+T was pressed")
else:
print("T was pressed")
public override void _Input(InputEvent @event)
{
if (@event is InputEventKey keyEvent && keyEvent.Pressed)
{
switch (keyEvent.Keycode)
{
case Key.T:
GD.Print(keyEvent.ShiftPressed ? "Shift+T was pressed" : "T was pressed");
break;
}
}
}
鼠标事件
鼠标事件继承自InputEventMouse
,并被分为InputEventMouseButton
和InputEventMouseMotion
两种类型。所有鼠标事件都包含position
属性。
鼠标按钮
捕获鼠标按钮与处理按键事件类似。@GlobalScope_MouseButton
包含了一系列鼠标按钮常量,如MOUSE_BUTTON_LEFT
和MOUSE_BUTTON_WHEEL_UP
:
func _input(event):
if event is InputEventMouseButton:
if event.button_index == MOUSE_BUTTON_LEFT and event.pressed:
print("Left button was clicked at ", event.position)
if event.button_index == MOUSE_BUTTON_WHEEL_UP and event.pressed:
print("Wheel up")
public override void _Input(InputEvent @event)
{
if (@event is InputEventMouseButton mouseEvent && mouseEvent.Pressed)
{
switch (mouseEvent.ButtonIndex)
{
case MouseButton.Left:
GD.Print($"Left button was clicked at {mouseEvent.Position}");
break;
case MouseButton.WheelUp:
GD.Print("Wheel up");
break;
}
}
}
鼠标行为
InputEventMouseMotion
在鼠标移动时触发,可以通过relative
属性获取移动的距离。下面是一个使用鼠标事件实现拖拽的示例:
extends Node
var dragging = false
var click_radius = 32 # Size of the sprite.
func _input(event):
if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT:
if (event.position - $Sprite2D.position).length() < click_radius:
# Start dragging if the click is on the sprite.
if not dragging and event.pressed:
dragging = true
# Stop dragging if the button is released.
if dragging and not event.pressed:
dragging = false
if event is InputEventMouseMotion and dragging:
# While dragging, move the sprite with the mouse.
$Sprite2D.position = event.position
using Godot;
public partial class MyNode2D : Node2D
{
private bool _dragging = false;
private int _clickRadius = 32; // Size of the sprite.
public override void _Input(InputEvent @event)
{
Sprite2D sprite = GetNodeOrNull<Sprite2D>("Sprite2D");
if (sprite == null)
{
return; // No suitable node was found.
}
if (@event is InputEventMouseButton mouseEvent && mouseEvent.ButtonIndex == MouseButton.Left)
{
if ((mouseEvent.Position - sprite.Position).Length() < _clickRadius)
{
// Start dragging if the click is on the sprite.
if (!_dragging && mouseEvent.Pressed)
{
_dragging = true;
}
}
// Stop dragging if the button is released.
if (_dragging && !mouseEvent.Pressed)
{
_dragging = false;
}
}
else
{
if (@event is InputEventMouseMotion motionEvent && _dragging)
{
// While dragging, move the sprite with the mouse.
sprite.Position = motionEvent.Position;
}
}
}
}
触摸事件
如果你使用的是触摸屏设备,就可以生成触摸事件。InputEventScreenTouch
相当于鼠标点击事件,而InputEventScreenDrag
的工作原理与鼠标移动一致。
在非触摸屏设备上测试触摸事件,可以在项目设置中启用“Emulate Touch From Mouse”选项。