You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Godot3.3.2报错:刷新查询时无法改状态,敌人死亡碰撞框不消失

问题解决方案

报错原因

Can't change this state while flushing queries. Use call_deferred() or set_deferred() to change monitoring state instead

该报错是Godot物理引擎的固有规则:当引擎处于物理帧的碰撞查询刷新阶段时,禁止直接修改碰撞体的启用/禁用状态。你触发报错的原因是在碰撞检测相关的回调逻辑中直接执行了$CollisionShape2D.disabled = true代码,刚好命中了物理查询的刷新周期。

修复步骤

  • 替换碰撞框禁用的实现方式,使用set_deferred延迟修改属性,等物理查询阶段结束后引擎会自动执行修改操作
  • 优化_physics_process的逻辑,敌人死亡后不再执行墙体检测、射线检测逻辑,避免无效操作

修改后的完整代码

extends KinematicBody2D

const GRAVITY = 10
const SPEED = 30 
const FLOOR = Vector2(0, -1)

var velocity = Vector2()

var direction = 1

var is_dead = false

func _ready():
    pass 
    
func dead():
    is_dead = true
    velocity = Vector2(0, 0)
    $AnimatedSprite.play("dead")
    # 替换为延迟调用修改碰撞框属性
    $CollisionShape2D.set_deferred("disabled", true)
    $Timer.start()

func _physics_process(delta):
    if is_dead == false:
        velocity.x = SPEED * direction
        
        if direction == 1:
            $AnimatedSprite.flip_h = false
        else:
            $AnimatedSprite.flip_h = true 
            
        $AnimatedSprite.play("walk")
        
        velocity.y += GRAVITY
        
        velocity = move_and_slide(velocity, FLOOR)
        
        # 把检测逻辑移到死亡判断内,死后不再执行
        if is_on_wall():
            direction = direction * -1
            $RayCast2D.position.x *= -1
            
        if $RayCast2D.is_colliding() == false:
            direction = direction * -1
            $RayCast2D.position.x *= -1


func _on_Timer_timeout():
    queue_free()

内容的提问来源于stack exchange,提问作者Snaza

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 19:15:04