使用get_tree创建计时器未激活——Pong游戏回合延迟异常
问题分析与解决方案
你的计时器没启动的核心问题是在_physics_process里直接用await打乱了帧回调的执行逻辑,加上already_collided的状态管理有漏洞,导致整个流程混乱。
具体问题点
_physics_process是每物理帧都会调用的函数,一旦在里面用await,函数会挂起,但下一帧引擎依然会再次调用_physics_process,此时already_collided的状态可能被错误重置。- 当RayCast不再碰撞时,你直接在else分支把
already_collided设为false,但此时如果还在3秒等待期,会导致状态提前失效,可能触发重复得分逻辑。 - 球重置后没有停止运动,就算等3秒,球可能已经自己动起来了,不符合“暂停后再开始”的需求。
修复后的代码
var already_collided = false var is_waiting = false # 新增:标记是否处于等待回合开始状态 func _physics_process(delta): if is_waiting: return # 等待期间直接跳过所有碰撞检测逻辑 if $RayCast2D.is_colliding() and not already_collided: already_collided = true start_round_reset(true) # 玩家2得分,传入true标记 elif not $RayCast2D.is_colliding() and already_collided: already_collided = false if $RayCast2D2.is_colliding() and not already_collided: already_collided = true start_round_reset(false) # 玩家1得分,传入false标记 elif not $RayCast2D2.is_colliding() and already_collided: already_collided = false # 单独的回合重置协程函数 func start_round_reset(is_p2_score): is_waiting = true # 重置球的位置并停止运动 $Ball.position = Vector2(575, 350) $Ball.velocity = Vector2.ZERO # 假设球用RigidBody2D,停止速度;如果是KinematicBody2D同理 # 更新得分 if is_p2_score: Globals.p2_score += 1 $Label2.text = str(Globals.p2_score) else: Globals.p1_score += 1 $Label.text = str(Globals.p1_score) # 等待3秒 await get_tree().create_timer(3).timeout # 3秒后启动新回合,给球一个初始速度(根据得分方决定方向) var initial_speed = 300 $Ball.velocity = Vector2(initial_speed if is_p2_score else -initial_speed, rand_range(-100, 100)) # 重置状态,允许下一次碰撞检测 is_waiting = false
改动说明
- 新增
is_waiting变量,确保在3秒等待期间完全跳过碰撞检测,避免逻辑冲突。 - 把回合重置逻辑抽成单独的协程函数
start_round_reset,不再在_physics_process里直接用await,避免干扰帧回调的正常执行。 - 重置球时先将速度设为0,确保球在等待期间静止,符合“暂停”的需求。
- 等待结束后给球赋予初始速度,方向根据得分方决定(比如玩家2得分,球向玩家1方向飞)。
内容的提问来源于stack exchange,提问作者Dagger
相关产品推荐
相关产品推荐

