如何在 Godot 中创建计时器?

Flu*_*es1 4 timer destroy gdscript godot

如何在 Godot 中创建一个计时器,在给定的时间后销毁脚本的对象?我希望在一段时间后从游戏中删除子弹以减少延迟。

The*_*aot 11

有一个Timer您可以使用的节点。您可以将其添加为子项,设置等待时间(以秒为单位) - 您可以将其设置为一次性,然后自动启动 - 将信号连接"timeout"到您的脚本,并在方法调用上queue_free拥有Node(和子项,其中包括)Timer被安全释放。


如果您愿意的话,您也可以通过代码来完成此操作。因此,让我们回顾一下我刚才所说的内容,但不是从编辑器中执行此操作,而是让我们看看等效的代码:

创建一个Timer,将其添加为子项:

var timer := Timer.new()
add_child(timer)
Run Code Online (Sandbox Code Playgroud)

设置等待时间(以秒为单位):

timer.wait_time = 1.0
Run Code Online (Sandbox Code Playgroud)

设置为一次性:

timer.one_shot = true
Run Code Online (Sandbox Code Playgroud)

timer.autostart = true让我们启动它,而不是将其设置为自动启动(这将是):

timer.start()
Run Code Online (Sandbox Code Playgroud)

"timeout"信号连接到方法。在这种情况下,我将调用该方法"_on_timer_timeout"

timer.connect("timeout", self, "_on_timer_timeout")

func _on_timer_timeout() -> void:
    pass
Run Code Online (Sandbox Code Playgroud)

然后在该方法中_on_timer_timeout,您可以调用queue_free

timer.connect("timeout", self, "_on_timer_timeout")

func _on_timer_timeout() -> void:
    queue_free()
Run Code Online (Sandbox Code Playgroud)


sla*_*lay 7

编辑:我的观点是正确的,最好的方法是使用像 Theraot 的答案所说的回调:

func _on_timer_timeout_funcname() -> void:
    # Do stuff here...
    queue_free() # removes this node from scene

var timer := Timer.new()
timer.wait_time = 1.0 # 1 second
timer.one_shot = true # don't loop, run once
timer.autostart = true # start timer when added to a scene
timer.connect("timeout", self, "_on_timer_timeout_funcname")
return add_child(timer)
Run Code Online (Sandbox Code Playgroud)

我将我的答案留在这里,供那些更喜欢顺序方法的人使用,但处理起来可能有点棘手。


Godot 4中,有一个简单的方法可以做到这一点:

# Do some action
await get_tree().create_timer(1.0).timeout # waits for 1 second
# Do something afterwards
queue_free() # Deletes this node (self) at the end of the frame
Run Code Online (Sandbox Code Playgroud)

重要提示:如果您在_process()_physics_process()函数中执行此操作,则每帧都会创建更多计时器,这会导致在运行以下代码之前同时发生多次运行。要处理这个问题,只需跟踪定时事件是否正在发生即可。

具有简单攻击逻辑的示例_process()

var attack_started = false;

func _process(delta):
    if attack_started:
        print("Not attacking, attack code running in background")
        return
    else:
        attack_started = true
        prepare_attack()
        await get_tree().create_timer(1.0).timeout # wait for 1 second
        begin_attack()
        attack_started = false
Run Code Online (Sandbox Code Playgroud)

await关键字适用于所有发出信号的事物,包括碰撞事件!

仅供参考:在 Godot 4 中yield被替换为awaitawait实际上只是等待信号/回调完成:

await object.signal
Run Code Online (Sandbox Code Playgroud)

get_tree().create_timer(5.0)将创建一个运行 5 秒的计时器,然后有一个timeout您可以点击的回调/信号。