Up to date
This page is up to date for Godot 4.2
.
If you still find outdated information, please open an issue.
輸入範例¶
前言¶
在本教學中, 您將學習如何使用Godot的 輸入事件 系統捕獲玩家輸入. 您的遊戲可以使用多種不同型別的輸入——鍵盤, 遊戲手柄, 滑鼠等等. 還有許多不同的方法, 將這些輸入轉化為遊戲中的動作. 本文將向您展示一些最常見的場景, 您可以將其作為您自己專案的起點.
備註
要詳細瞭解 Godot 的輸入事件系統是如何工作的,請參閱 使用 InputEvent。
事件和輪詢¶
有時你想讓你的遊戲對某一輸入事件作出反應--例如按下 "跳躍" 按鈕. 在其他情況下, 你可能希望只要有一個鍵被按下就會發生一些事情, 比如移動. 在第一種情況下, 你可以使用 _input()
函式, 只要有輸入事件發生就會呼叫該函式. 在第二種情況下,Godot提供了 Input 單例, 你可以用它來查詢一個輸入的狀態.
範例:
func _input(event):
if event.is_action_pressed("jump"):
jump()
func _physics_process(delta):
if Input.is_action_pressed("move_right"):
# Move as long as the key/button is pressed.
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"))
{
// Move as long as the key/button is pressed.
position.X += speed * (float)delta;
}
}
這使您能夠靈活地混合和配對所執行輸入的處理型別.
對於本教學的其餘部分, 我們將專注於使用 _input ()
捕捉單個事件.
輸入事件¶
輸入事件是繼承自 輸入事件 的物件. 根據事件型別, 物件將包含與該事件相關的特定屬性. 為了瞭解事件的實際情況, 新增一個節點並附加以下腳本:
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());
}
}
當你按下按鍵, 移動滑鼠, 並執行其他輸入, 您會在輸出視窗中看到每個事件滾動. 下面是輸出的一個例子:
A
Mouse motion at position ((971, 5)) with velocity ((0, 0))
Right Mouse Button
Mouse motion at position ((870, 243)) with velocity ((0.454937, -0.454937))
Left Mouse Button
Mouse Wheel Up
A
B
Shift
Alt+Shift
Alt
Shift+T
Mouse motion at position ((868, 242)) with velocity ((-2.134768, 2.134768))
如你所見, 對於不同型別的輸入, 結果是非常不同的. 按鍵事件甚至被列印為按鍵符號. 例如, 讓我們考慮 滑鼠按鈕輸入事件 . 它繼承自以下類:
InputEvent - 所有輸入事件的基底類別
InputEventWithModifiers - 增加了檢查是否按下修飾按鍵, 如 Shift 或 Alt .
InputEventMouse - 增加滑鼠事件屬性, 如
position
滑鼠按鈕輸入事件 包含按下的按鈕的索引, 無論是按兩下, 或是其他.
小訣竅
在處理事件時, 打開類引用是一個好主意, 這樣可以檢查事件型別的可用屬性和方法.
如果您嘗試存取不包含屬性的輸入型別上的屬性, 則可能會遇到錯誤-例如, 對 InputEventKey
呼叫 Position
. 要避免這種情況, 請確保首先測試事件型別:
func _input(event):
if event is InputEventMouseButton:
print("mouse button event at ", event.position)
public override void _Input(InputEvent @event)
{
if (@event is InputEventMouseButton mouseEvent)
{
GD.Print("mouse button event at ", mouseEvent.Position);
}
}
InputMap¶
事件表 是處理各種輸入的最靈活的方法. 您可以通過建立命名的輸入 動作 來使用它, 可以為它分配任意數量的輸入事件, 例如按鍵或滑鼠點擊. 一個新的Godot專案已經包含許多預設定義操作. 看看它們, 然後新增你自己的, 打開專案->專案設定, 並選擇事件表分頁:
小訣竅
新的 Godot 專案包含許多已定義的預設操作。若要查看它們,請在“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");
}
}
}
小訣竅
詳見 全域範圍_鍵位列表 獲取掃描程式碼常數列表.
警告
由於*鍵盤衝突*,如果你一次性按下了太多的鍵,那麼在特定時間點,可能是無法將所有按鍵輸入都進行註冊的。根據按鍵在鍵盤上位置的不同,某些按鍵產生衝突的可能性會比其他的要高。有些鍵盤在硬體層面會提供抗衝突功能,不過在低端鍵盤和筆記本鍵盤上很少見。
因此,建議使用能夠在不具備抗衝突功能的鍵盤上也能正常工作的預設鍵盤配置。詳情請參閱`這個 Gamedev Stack Exchange 問題 <https://gamedev.stackexchange.com/a/109002>`__。
鍵盤修飾鍵¶
修飾鍵屬性繼承自 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
屬性。
滑鼠行為¶
InputEventMouseMotion 只要滑鼠移動就會發生事件. 可以通過 relative
屬性找到移動的距離.
下面是一個使用滑鼠事件拖放 Sprite 節點的例子:
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 的工作原理與滑鼠移動一致。
小訣竅
要在非觸控式螢幕裝置上測試觸摸事件,請打開“專案設定”,進入“Input Devices/Pointing”(輸入裝置/觸點)部分。啟用“Emulate Touch From Mouse”(根據滑鼠類比觸摸),您的專案將把滑鼠按一下和移動解釋為觸摸事件。