Reputation: 21
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
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
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