Input.is_action_just_pressed
2026/4/14大约 6 分钟
最后同步日期:2026-04-15 | Godot 官方原文 — Input.is_action_just_pressed
Input.is_action_just_pressed
定义
想象你按了一下电梯按钮——你只需要按一次,电梯就会记住你的请求。就算你一直把手指放在按钮上,电梯也不会因为你"按着不放"就多派几部电梯来。
is_action_just_pressed 就是这个逻辑:它只在玩家按下按键的那一帧返回 true。之后即使你继续按着不放,它也会返回 false。
一句话总结
is_action_just_pressed = "你刚才那一瞬间按了吗?"——只在按下那一帧返回 true,之后哪怕继续按着也返回 false。
和 is_action_pressed 的区别
is_action_just_pressed:只在按下那一瞬间返回true(适合跳跃、交互、打开背包等一次性操作)is_action_pressed:按住不放期间,每一帧都返回true(适合移动、射击等持续操作)
函数签名
C#
public static bool IsActionJustPressed(StringName action, bool exactMatch = false)GDScript
is_action_just_pressed(action: StringName, exact_match: bool = false) -> bool参数说明
| 参数 | 类型 | 必需 | 说明 |
|---|---|---|---|
| action | StringName | 是 | 动作名称,在项目设置(Project Settings -> Input Map)中定义。比如 "jump"、"interact" |
| exactMatch | bool | 否 | 是否精确匹配。默认 false;设为 true 时只匹配完全相同的输入设备,不允许不同设备的动作互相触发 |
返回值
bool — 如果指定的动作在当前帧刚刚被按下,返回 true;否则返回 false。
代码示例
基础用法
最简单的用法——检测玩家是否刚刚按下了跳跃键:
C#
using Godot;
public partial class TestInput : Node
{
public override void _Process(double delta)
{
// 检测 "jump" 动作是否在当前帧刚刚被按下
if (Input.IsActionJustPressed("jump"))
{
GD.Print("玩家按下了跳跃键!");
}
// 运行结果: (按空格键那一帧)打印 "玩家按下了跳跃键!"
// (继续按住)不再打印
// (松开后再次按下)再次打印一次
}
}GDScript
extends Node
func _process(delta: float) -> void:
# 检测 "jump" 动作是否在当前帧刚刚被按下
if Input.is_action_just_pressed("jump"):
print("玩家按下了跳跃键!")
# 运行结果: (按空格键那一帧)打印 "玩家按下了跳跃键!"
# (继续按住)不再打印
# (松开后再次按下)再次打印一次实际场景
在一个 2D 平台跳跃游戏中,用 is_action_just_pressed 实现跳跃——按一次跳一次,按住不会连跳:
C#
using Godot;
public partial class PlatformPlayer : CharacterBody2D
{
[Export] public float ExMoveSpeed = 300f;
[Export] public float ExJumpForce = -400f;
private float _gravity = 980f;
private int _jumpCount = 0;
private int _maxJumps = 2; // 允许二段跳
public override void _PhysicsProcess(double delta)
{
Vector2 velocity = Velocity;
// 左右移动(用 is_action_pressed,因为是持续动作)
float direction = 0f;
if (Input.IsActionPressed("move_left")) direction -= 1f;
if (Input.IsActionPressed("move_right")) direction += 1f;
velocity.X = direction * ExMoveSpeed;
// 跳跃(用 is_action_just_pressed,因为是一次性动作)
if (Input.IsActionJustPressed("jump"))
{
if (_jumpCount < _maxJumps)
{
velocity.Y = ExJumpForce;
_jumpCount++;
GD.Print($"跳跃!第 {_jumpCount} 段跳");
// 运行结果: 跳跃!第 1 段跳
// (空中再按一次)跳跃!第 2 段跳
}
}
// 重力
if (!IsOnFloor())
{
velocity.Y += _gravity * (float)delta;
}
else
{
_jumpCount = 0; // 着地后重置跳跃次数
}
Velocity = velocity;
MoveAndSlide();
}
}GDScript
extends CharacterBody2D
@export var ex_move_speed: float = 300.0
@export var ex_jump_force: float = -400.0
var _gravity: float = 980.0
var _jump_count: int = 0
var _max_jumps: int = 2 # 允许二段跳
func _physics_process(delta: float) -> void:
var velocity := velocity
# 左右移动(用 is_action_pressed,因为是持续动作)
var direction := 0.0
if Input.is_action_pressed("move_left"): direction -= 1.0
if Input.is_action_pressed("move_right"): direction += 1.0
velocity.x = direction * ex_move_speed
# 跳跃(用 is_action_just_pressed,因为是一次性动作)
if Input.is_action_just_pressed("jump"):
if _jump_count < _max_jumps:
velocity.y = ex_jump_force
_jump_count += 1
print("跳跃!第 %d 段跳" % _jump_count)
# 运行结果: 跳跃!第 1 段跳
# (空中再按一次)跳跃!第 2 段跳
# 重力
if not is_on_floor():
velocity.y += _gravity * delta
else:
_jump_count = 0 # 着地后重置跳跃次数
self.velocity = velocity
move_and_slide()进阶用法
结合 is_action_just_pressed 实现多种一次性操作:交互、切换武器、打开/关闭背包面板:
C#
using Godot;
public partial class GamePlayer : CharacterBody2D
{
// 导出属性
[Export] public float ExMoveSpeed = 300f;
[Export] public Godot.Collections.Array<PackedScene> ExWeaponScenes = new();
// 内部变量
private int _currentWeaponIndex = 0;
private bool _inventoryOpen = false;
private CanvasLayer _inventoryUI;
private Label _interactionLabel;
public override void _Ready()
{
_inventoryUI = GetNode<CanvasLayer>("InventoryUI");
_interactionLabel = GetNode<Label>("HUD/InteractionLabel");
_inventoryUI.Visible = false;
_interactionLabel.Text = "";
}
public override void _Process(double delta)
{
// 1. 切换武器:按 Q 切到上一把,按 E 切到下一把
if (Input.IsActionJustPressed("prev_weapon"))
{
_currentWeaponIndex = (_currentWeaponIndex - 1 + ExWeaponScenes.Count) % ExWeaponScenes.Count;
GD.Print($"切换武器: 槽位 {_currentWeaponIndex}");
// 运行结果: 切换武器: 槽位 2
}
if (Input.IsActionJustPressed("next_weapon"))
{
_currentWeaponIndex = (_currentWeaponIndex + 1) % ExWeaponScenes.Count;
GD.Print($"切换武器: 槽位 {_currentWeaponIndex}");
// 运行结果: 切换武器: 槽位 1
}
// 2. 打开/关闭背包:按 Tab 切换
if (Input.IsActionJustPressed("toggle_inventory"))
{
_inventoryOpen = !_inventoryOpen;
_inventoryUI.Visible = _inventoryOpen;
GD.Print(_inventoryOpen ? "背包已打开" : "背包已关闭");
// 运行结果: 背包已打开(按 Tab 后)
// 背包已关闭(再按一次 Tab 后)
}
// 3. 交互:按 F 与附近的物体交互
if (Input.IsActionJustPressed("interact"))
{
var interactable = FindNearbyInteractable();
if (interactable != null)
{
GD.Print($"与 {interactable.Name} 交互");
// 运行结果: 与 Chest_01 交互
}
}
}
private Node2D FindNearbyInteractable()
{
// 查找附近可交互物体的简化实现
return null;
}
}GDScript
extends CharacterBody2D
# 导出属性
@export var ex_move_speed: float = 300.0
@export var ex_weapon_scenes: Array[PackedScene] = []
# 内部变量
var _current_weapon_index: int = 0
var _inventory_open: bool = false
var _inventory_ui: CanvasLayer
var _interaction_label: Label
func _ready() -> void:
_inventory_ui = get_node("InventoryUI")
_interaction_label = get_node("HUD/InteractionLabel")
_inventory_ui.visible = false
_interaction_label.text = ""
func _process(delta: float) -> void:
# 1. 切换武器:按 Q 切到上一把,按 E 切到下一把
if Input.is_action_just_pressed("prev_weapon"):
_current_weapon_index = (_current_weapon_index - 1 + ex_weapon_scenes.size()) % ex_weapon_scenes.size()
print("切换武器: 槽位 %d" % _current_weapon_index)
# 运行结果: 切换武器: 槽位 2
if Input.is_action_just_pressed("next_weapon"):
_current_weapon_index = (_current_weapon_index + 1) % ex_weapon_scenes.size()
print("切换武器: 槽位 %d" % _current_weapon_index)
# 运行结果: 切换武器: 槽位 1
# 2. 打开/关闭背包:按 Tab 切换
if Input.is_action_just_pressed("toggle_inventory"):
_inventory_open = not _inventory_open
_inventory_ui.visible = _inventory_open
print("背包已打开" if _inventory_open else "背包已关闭")
# 运行结果: 背包已打开(按 Tab 后)
# 背包已关闭(再按一次 Tab 后)
# 3. 交互:按 F 与附近的物体交互
if Input.is_action_just_pressed("interact"):
var interactable = _find_nearby_interactable()
if interactable:
print("与 %s 交互" % interactable.name)
# 运行结果: 与 Chest_01 交互
func _find_nearby_interactable() -> Node2D:
# 查找附近可交互物体的简化实现
return null注意事项
- 只在按下那一帧触发:
is_action_just_pressed只会在玩家刚刚按下按键的那一帧返回true。之后即使继续按着不放,也会返回false。这使它非常适合跳跃、交互、切换武器等"按一次执行一次"的操作。 - 不要用于持续移动:如果你用它来控制角色移动,玩家就必须不停地按键才能移动(按一下走一帧)。持续移动请用
is_action_pressed。 - 必须在 Input Map 中定义动作:调用此方法前,需要先在 Godot 编辑器的 项目设置 -> Input Map 中定义对应的动作名称。如果传入了未定义的动作名称,不会报错,但会始终返回
false。 - 帧的概念:"当前帧"指的是游戏循环中的单次更新。如果游戏以 60fps 运行,那么按住按键不放时,
is_action_just_pressed只在按下的那 1/60 秒内返回true。 - C# 差异:C# 中方法名用 PascalCase(
Input.IsActionJustPressed),GDScript 中用 snake_case(Input.is_action_just_pressed)。
