BLAZE GAMING
BLAZE GAMING

Reputation: 21

godot 4 GameManager.gd:47 @ _on_area_2d_body_shape_entered(): This function can't be used during the in/out signal

hello ive been working on this godot project but get an error when trying to switch scenes the first time i switch from level 1 to 2 i get the error message stated in the title but it changes succesfully but when i try to change from level 2 to 3 it doesnt work

heres the code

extends Node

@onready var shuriken_count = %shuriken_count
var shurikens = 0
const Maxhealth = 100

var health = Maxhealth
 

@onready var health_bar = $"../UI/TextureProgressBar"

@onready var level_1 = $".."


# Called when the node enters the scene tree for the first time.
func _ready():
    health_bar.max_value = Maxhealth
    sethealthbar()
    
func sethealthbar():
    health_bar.value = health

func damage():
    health -= 20
    if health < 0:
        resetlevel()
    sethealthbar()
    
func resetlevel():
    get_tree().reload_current_scene()




func increaseshurikens():
    shurikens += 1
    shuriken_count.text = "shurikens: " + str(shurikens)
    
func decreaseshurikens():
    shurikens -= 1
    shuriken_count.text = "shurikens: " + str(shurikens)


func _on_area_2d_body_shape_entered(_body_rid, body, _body_shape_index, _local_shape_index):
    if (body.name == "CharacterBody2D"):
        Levels.level +=1
        get_tree().change_scene_to_file("res://scenes/level_"+ str(Levels.level) +".tscn")

Upvotes: 2

Views: 2514

Answers (2)

Theraot
Theraot

Reputation: 40295

The following is my reasoning about the errors:

  • The error in question happens because the Area2D is in use while changing from one space to another. Which, I believe is because the Area2D is in an autoload while you change the scene.

    Yes, using call_deffered as pointed in Bugfish's answer would address that.

  • The error you posted in comments suggest you are trying to access some physics body while the transition is not done, which I presume that is in another autoload.

    In particular the error says "body->get_space()" is null, you can check that:

    func _physics_process(delta:float) -> void:
        if not PhysicsServer2D.body_get_space(get_rid()).is_valid():
            return
    
        # rest of the code
    

    The code above is written for a script attached to a physics object. If the problematic script is not a physics object, but uses one, you would want to use get_rid() on a reference to the physics object (e.g. my_physics_object.get_rid()) instead of just get_rid() in the code above.

However, that seems to be patching the issue, instead of getting a proper solution. So I can't guarantee another error won't pop up from some other part of your code.

So based on Bugfish's answer, and assuming the code in question is an autoload, you could do this:

var changing_scene:bool = false


func _on_area_2d_body_shape_entered(_body_rid, body, _body_shape_index, _local_shape_index):
    if (body.name == "CharacterBody2D"):
        changing_scene = true
        call_deffered("change_level")

func change_level():
    Levels.level +=1
    var scene_path := "res://scenes/level_"+ str(Levels.level) +".tscn"
    var err := get_tree().change_scene_to_file(scene_path)
    if err == OK:
        changing_scene = false
    else:
        print("Error " + str(err) + " changing scene to " + scene_path)

Then the other autoloads can check changing_scene and if it is true, stop whatever they are doing until it is false again. If the code in question is not an autoload, you might want to move changing_scene to an autoload for ease of access from other parts of the code.

Also, I added a print that will tell you if there was an error loading the new scene. If there was, check if the scene file exists and can be loaded correctly in the editor.

Upvotes: 1

Bugfish
Bugfish

Reputation: 1729

As the error states functions that remove nodes from the tree should not be called in signals.

Instead use call_deffered so the code is executed at the end of the frame:

func _on_area_2d_body_shape_entered(_body_rid, body, _body_shape_index, _local_shape_index):
    if (body.name == "CharacterBody2D"):
        call_deffered("change_level")

func change_level():
    Levels.level +=1
    get_tree().change_scene_to_file("res://scenes/level_"+ str(Levels.level) +".tscn")

Upvotes: 3

Related Questions