1

Hello I am working on a pong game in godot. Everything is going well so far but I recieve this error in my debugger:

E 0:01:55.112 body_set_shape_as_one_way_collision: Can't change this state while flushing queries. Use call_deferred() or set_deferred() to change monitoring state instead.

<C++ Error> Condition "body->get_space() && flushing_queries" is true.

<C++ Source> servers/physics_2d/physics_2d_server_sw.cpp:739 @ body_set_shape_as_one_way_collision()

AddBall.gd:18 @ _on_Area2D_body_entered()

Here is my code for instancing a duplicate ball:

extends Node2D

var collect = false
var ballscene = null

func _ready():
    $Area2D/AnimatedSprite.play("Spin")

func _on_Area2D_body_entered(body):
    #print(body.name)
    if body.name=="Ball"&&collect==false:
        collect = true
        $Collection.play()
        $AnimationPlayer.play("Fade")
        $Area2D/AnimatedSprite.stop()
        var ball =  load("res://Scenes/BallDuplicate.tscn")
        ballscene = ball.instance()
        find_parent("SpawnManager").get_node("BallDuplicate").add_child(ballscene)
        queue_free()
        

Yes, I instance the ball in the power up and not my spawn manager.

LeoDog896
  • 3,472
  • 1
  • 15
  • 40
  • I recommend editing your question to be more generic. The issue is in your specific Pong game, but the generic error is about adding a child during the physics loop. Also it will help if you provide the simplest code snippet possible that reproduces your problem, so we can copy&paste&run it in our editor. – WebF0x Aug 14 '22 at 21:30
  • Does this answer your question? [Godot 3.2.1. Can't change this state while flushing queries. Use call\_deferred() or set\_deferred() to change monitoring state instead](https://stackoverflow.com/questions/63206231/godot-3-2-1-cant-change-this-state-while-flushing-queries-use-call-deferred) – WebF0x Aug 14 '22 at 21:56

2 Answers2

2

As the error message recommends, you should postpone your node tree changes with call_deffered() as you are not allowed to kick in with adding another rigid bodies to the scene during collision processing.

extends Node2D

var collect = false
var ballscene = null

func CollectFunc():
    if not collect:
        collect = true
        $Collection.play()
        $AnimationPlayer.play("Fade")
        $Area2D/AnimatedSprite.stop()
        var ball =  load("res://Scenes/BallDuplicate.tscn")
        ballscene = ball.instance()
        find_parent("SpawnManager").get_node("BallDuplicate").add_child(ballscene)
        queue_free()

func _ready():
    $Area2D/AnimatedSprite.play("Spin")

func _on_Area2D_body_entered(body):
    #print(body.name)
    if body.name=="Ball":
        call_deffered("CollectFunc")
Oliort UA
  • 1,568
  • 1
  • 14
  • 31
2

Another alternative is to setup your collisions-related signal so that it calls its callback method in "deferred mode".

In the UI, check the "Deferred" box: Connecting signal to method with "Deferred" checkbox checked

Or in GDScript, connect the signal with the "CONNECT_DEFERRED" flag:

$Area2D.connect("body_entered", self, "_on_Area2D_body_entered", [], CONNECT_DEFERRED)
WebF0x
  • 165
  • 9