断开SceneTreeTimer后为何未显示为已删除对象?
手动触发SceneTreeTimer的timeout信号后,为何定时器对象未被标记为[Deleted Object]?
我尝试断开SceneTreeTimer的信号,避免其超时后调用指定函数,代码实现如下:
extends Node2D onready var something = $Node2D var timer func abort(): timer.disconnect("timeout",something,"queue_free") timer.emit_signal("timeout") print("timer=",timer) func _ready(): timer=get_tree().create_timer(3) timer.connect("timeout",something,"queue_free") ... abort()
虽然操作阻止了定时器调用目标函数,但执行abort()后打印timer,结果显示为timer=>[SceneTreeTimer:1276]。按逻辑,定时器时间已过应该显示为[Deleted Object],这是为什么?
这是因为SceneTreeTimer的自动销毁逻辑只在自然超时时才会触发,手动调用emit_signal("timeout")仅仅是触发了信号事件,并不会触发SceneTree对定时器的销毁流程。
具体拆解你的代码流程:
- 在
_ready中创建了一个3秒的定时器,同时连接了timeout信号到something的queue_free方法 - 你立刻调用了
abort(),此时定时器还没走到设定的3秒计时终点,自然超时的逻辑根本没触发 - 断开信号只是切断了目标函数的调用链路,但定时器本身的生命周期完全不受影响;手动触发
timeout信号也只是模拟了超时的信号触发,并没有启动SceneTree内置的定时器销毁机制
另外补充一点:就算等定时器自然超时,它也不会立刻变成[Deleted Object]——SceneTree会在当前帧的逻辑处理结束后,才会清理掉已经完成计时的定时器对象。你手动触发信号的操作完全绕开了这套自动销毁流程,所以定时器对象依然保持有效引用,打印出来就是正常的对象实例,而非已删除标记。
如果想要主动销毁定时器,可以调用timer.stop(),这会让SceneTree清理掉这个定时器对象,之后再打印就会看到[Deleted Object]了。
内容的提问来源于stack exchange,提问作者cak3_lover
相关产品推荐
相关产品推荐

