Input.action_press
2026/4/14大约 7 分钟
最后同步日期:2026-04-15 | Godot 官方原文 — Input.action_press
Input.action_press
定义
想象你正在玩游戏,你的角色需要跳起来——你按下空格键,角色就跳了。但有些时候,你不想让玩家按键,而是想让游戏代码自己"假装"按了一下按键。比如:踩到地雷时自动触发"受伤"动作,或者在过场动画中让角色自动执行某个操作。
action_press 就是干这个的——它在代码里模拟一次按键按下,效果跟玩家真的按了那个键一模一样。游戏里所有监听这个动作的代码都会被触发,就好像玩家亲手按了一样。
一句话总结
action_press = "让代码替玩家按一下按键"——模拟按下动作,触发所有相关的事件响应。
和真实按键的区别
action_press 是纯代码模拟的,不会产生底层的 InputEvent 事件。也就是说,_Input、_UnhandledInput 等回调函数不会收到这个模拟的按键事件。它只影响 is_action_pressed、get_action_strength 等 Input 类的查询方法。
函数签名
C#
public static void ActionPress(string action, float strength = 1.0f)GDScript
Input.action_press(action: String, strength: float = 1.0) -> void参数说明
| 参数 | 类型 | 必需 | 说明 |
|---|---|---|---|
| action | string | 是 | 要模拟按下的动作名称,在项目设置(Project Settings -> Input Map)中定义。比如 "jump"、"shoot" |
| strength | float | 否 | 按键力度,范围 0.0 到 1.0。默认 1.0 表示完全按下。可以用来模拟手柄摇杆的部分按压(比如轻轻推摇杆,力度只有 0.5) |
返回值
此函数没有返回值(void)。
代码示例
基础用法
最简单的用法——在代码中模拟按下"跳跃"动作:
C#
using Godot;
public partial class TestActionPress : Node
{
public override void _Ready()
{
// 模拟按下 "jump" 动作(相当于玩家按了一下跳跃键)
Input.ActionPress("jump");
// 检查动作是否被按下(现在应该是 true)
GD.Print("jump 被按下了吗? " + Input.IsActionPressed("jump"));
// 运行结果: jump 被按下了吗? True
// 注意:action_press 是"按下不松开"的状态
// 如果要"松开",需要调用 ActionRelease
}
}GDScript
extends Node
func _ready() -> void:
# 模拟按下 "jump" 动作(相当于玩家按了一下跳跃键)
Input.action_press("jump")
# 检查动作是否被按下(现在应该是 true)
print("jump 被按下了吗? " + str(Input.is_action_pressed("jump")))
# 运行结果: jump 被按下了吗? True
# 注意:action_press 是"按下不松开"的状态
# 如果要"松开",需要调用 action_release实际场景
在一个平台跳跃游戏中,当角色踩到弹跳板时,自动模拟一次跳跃动作——不需要玩家手动按跳跃键:
C#
using Godot;
public partial class BouncePad : Area2D
{
[Export] public float ExBounceStrength = 1.0f;
public override void _Ready()
{
// 当有物体进入弹跳板区域时触发
BodyEntered += OnBodyEntered;
}
private void OnBodyEntered(Node2D body)
{
// 检查踩上来的是不是玩家
if (body is Player player)
{
// 模拟按下跳跃动作,力度由弹跳板强度决定
Input.ActionPress("jump", ExBounceStrength);
GD.Print("踩到弹跳板!自动跳跃,力度: " + ExBounceStrength);
// 运行结果: 踩到弹跳板!自动跳跃,力度: 1
// 延迟一段时间后自动松开(模拟松手)
// 这里用简单的方式:在下一帧释放
CallDeferred(nameof(ReleaseJump));
}
}
private void ReleaseJump()
{
Input.ActionRelease("jump");
GD.Print("弹跳板自动释放跳跃");
// 运行结果: 弹跳板自动释放跳跃
}
}GDScript
extends Area2D
@export var ex_bounce_strength: float = 1.0
func _ready() -> void:
# 当有物体进入弹跳板区域时触发
body_entered.connect(_on_body_entered)
func _on_body_entered(body: Node2D) -> void:
# 检查踩上来的是不是玩家
if body is Player:
# 模拟按下跳跃动作,力度由弹跳板强度决定
Input.action_press("jump", ex_bounce_strength)
print("踩到弹跳板!自动跳跃,力度: " + str(ex_bounce_strength))
# 运行结果: 踩到弹跳板!自动跳跃,力度: 1.0
# 延迟一帧后自动松开(模拟松手)
call_deferred("_release_jump")
func _release_jump() -> void:
Input.action_release("jump")
print("弹跳板自动释放跳跃")
# 运行结果: 弹跳板自动释放跳跃进阶用法
实现一个回放系统——记录玩家的操作并在之后重放。用 action_press 和 action_release 来精确重现玩家的每一步操作:
C#
using Godot;
public partial class InputReplay : Node
{
// 记录的操作条目
private readonly record ReplayAction(string Action, bool IsPressed, double Time);
private Godot.Collections.Array<ReplayAction> _recordedActions = new();
private double _recordStartTime;
private bool _isRecording = false;
private bool _isPlaying = false;
private int _playbackIndex = 0;
private double _playbackStartTime;
public override void _Ready()
{
StartRecording();
}
public override void _UnhandledInput(InputEvent @event)
{
if (!_isRecording) return;
// 记录玩家的按键操作
foreach (string action in new[] { "move_left", "move_right", "jump", "shoot" })
{
if (@event.IsActionPressed(action))
{
double time = Time.GetTicksMsec() / 1000.0 - _recordStartTime;
_recordedActions.Add(new ReplayAction(action, true, time));
GD.Print($"记录: 按下 {action} @ {time:F2}s");
// 运行结果: 记录: 按下 jump @ 1.35s
}
else if (@event.IsActionReleased(action))
{
double time = Time.GetTicksMsec() / 1000.0 - _recordStartTime;
_recordedActions.Add(new ReplayAction(action, false, time));
GD.Print($"记录: 松开 {action} @ {time:F2}s");
// 运行结果: 记录: 松开 jump @ 1.50s
}
}
// 按 R 键停止录制并开始回放
if (@event.IsActionPressed("replay"))
{
StartPlayback();
}
}
private void StartRecording()
{
_isRecording = true;
_isPlaying = false;
_recordedActions.Clear();
_recordStartTime = Time.GetTicksMsec() / 1000.0;
GD.Print("=== 开始录制操作 ===");
// 运行结果: === 开始录制操作 ===
}
private void StartPlayback()
{
_isRecording = false;
_isPlaying = true;
_playbackIndex = 0;
_playbackStartTime = Time.GetTicksMsec() / 1000.0;
GD.Print("=== 开始回放,共 " + _recordedActions.Count + " 个操作 ===");
// 运行结果: === 开始回放,共 12 个操作 ===
}
public override void _Process(double delta)
{
if (!_isPlaying || _playbackIndex >= _recordedActions.Count) return;
double currentTime = Time.GetTicksMsec() / 1000.0 - _playbackStartTime;
// 重放所有到时间的操作
while (_playbackIndex < _recordedActions.Count &&
_recordedActions[_playbackIndex].Time <= currentTime)
{
var action = _recordedActions[_playbackIndex];
if (action.IsPressed)
{
Input.ActionPress(action.Action);
GD.Print($"回放: 按下 {action.Action} @ {currentTime:F2}s");
// 运行结果: 回放: 按下 jump @ 1.35s
}
else
{
Input.ActionRelease(action.Action);
GD.Print($"回放: 松开 {action.Action} @ {currentTime:F2}s");
// 运行结果: 回放: 松开 jump @ 1.50s
}
_playbackIndex++;
}
if (_playbackIndex >= _recordedActions.Count)
{
_isPlaying = false;
GD.Print("=== 回放结束 ===");
// 运行结果: === 回放结束 ===
}
}
}GDScript
extends Node
# 记录的操作条目
var _recorded_actions: Array = []
var _record_start_time: float = 0.0
var _is_recording: bool = false
var _is_playing: bool = false
var _playback_index: int = 0
var _playback_start_time: float = 0.0
func _ready() -> void:
_start_recording()
func _unhandled_input(event: InputEvent) -> void:
if not _is_recording:
return
# 记录玩家的按键操作
for action in ["move_left", "move_right", "jump", "shoot"]:
if event.is_action_pressed(action):
var time := Time.get_ticks_msec() / 1000.0 - _record_start_time
_recorded_actions.append({"action": action, "pressed": true, "time": time})
print("记录: 按下 %s @ %.2fs" % [action, time])
# 运行结果: 记录: 按下 jump @ 1.35s
elif event.is_action_released(action):
var time := Time.get_ticks_msec() / 1000.0 - _record_start_time
_recorded_actions.append({"action": action, "pressed": false, "time": time})
print("记录: 松开 %s @ %.2fs" % [action, time])
# 运行结果: 记录: 松开 jump @ 1.50s
# 按 R 键停止录制并开始回放
if event.is_action_pressed("replay"):
_start_playback()
func _start_recording() -> void:
_is_recording = true
_is_playing = false
_recorded_actions.clear()
_record_start_time = Time.get_ticks_msec() / 1000.0
print("=== 开始录制操作 ===")
# 运行结果: === 开始录制操作 ===
func _start_playback() -> void:
_is_recording = false
_is_playing = true
_playback_index = 0
_playback_start_time = Time.get_ticks_msec() / 1000.0
print("=== 开始回放,共 %d 个操作 ===" % _recorded_actions.size())
# 运行结果: === 开始回放,共 12 个操作 ===
func _process(delta: float) -> void:
if not _is_playing or _playback_index >= _recorded_actions.size():
return
var current_time := Time.get_ticks_msec() / 1000.0 - _playback_start_time
# 重放所有到时间的操作
while _playback_index < _recorded_actions.size() and \
_recorded_actions[_playback_index]["time"] <= current_time:
var entry = _recorded_actions[_playback_index]
if entry["pressed"]:
Input.action_press(entry["action"])
print("回放: 按下 %s @ %.2fs" % [entry["action"], current_time])
# 运行结果: 回放: 按下 jump @ 1.35s
else:
Input.action_release(entry["action"])
print("回放: 松开 %s @ %.2fs" % [entry["action"], current_time])
# 运行结果: 回放: 松开 jump @ 1.50s
_playback_index += 1
if _playback_index >= _recorded_actions.size():
_is_playing = false
print("=== 回放结束 ===")
# 运行结果: === 回放结束 ===注意事项
- 不会产生 InputEvent 事件:
action_press模拟的按键按下不会触发InputEvent。也就是说,_Input、_UnhandledInput等回调函数收不到这个模拟事件。它只影响Input.IsActionPressed、Input.GetActionStrength等查询方法的结果。如果你需要在_UnhandledInput中捕获模拟事件,应该使用Input.ParseInputEvent来手动创建和发送一个InputEventAction。 - 按下后不会自动松开:调用
action_press后,该动作会一直保持"按下"状态,直到你显式调用action_release。如果你只是想模拟一次短暂的按键(按一下就松开),必须手动在合适的时机调用action_release。 - strength 参数的作用:
strength参数会影响Input.GetActionStrength的返回值。对于普通键盘按键,力度要么是 0(没按)要么是 1(按了);但对于手柄摇杆之类的模拟输入,力度可以是 0 到 1 之间的任意值。你可以利用这一点在代码中模拟不同程度的按压。 - 必须在 Input Map 中定义动作:和所有动作相关的方法一样,调用前需要先在 Godot 编辑器的 项目设置 -> Input Map 中定义对应的动作名称。如果传入了未定义的动作名称,不会报错,但也不会产生任何效果。
- 适合做 AI 控制:
action_press和action_release非常适合用来给 AI 角色"注入"输入。AI 不需要真的按键,只需要在代码中调用这两个方法,就可以和玩家角色共享同一套输入处理逻辑,减少重复代码。 - C# 差异:C# 中方法名用 PascalCase(
Input.ActionPress),GDScript 中用 snake_case(Input.action_press)。
