Godot Version
Godot 4.2.2
Question
So basically I am trying to make a Super Mario 2D platformer game. When the player wins the scene is changed to a CanvasLayer that informs the player that he won. The thing is that my game has checkpoints and when the scene gets changed to a level, the player spawn from the checkpoint. So I tried to change the scene and then reload it, but its says that ""Cannot call method 'reload_current_scene' on a null value.
var player_won : bool
@onready var game_over_screen_label = $PanelContainer/MarginContainer/Rows/GameOverLabel
func _ready():
if player_won :
game_over_screen_label.text = "YOU WIN"
var setting : LabelSettings = LabelSettings.new()
setting.outline_color = Color.GREEN
setting.outline_size = 3
setting.font_size = 80
setting.font_color = Color.BLACK
game_over_screen_label.label_settings = setting
### THIS IS THE PROBLEM
func _on_restart_button_pressed():
get_tree().paused = false
get_tree().change_scene_to_file("res://Scenes/Levels/level_one.tscn")
get_tree().reload_current_scene()
func _on_quit_button_pressed():
get_tree().paused = false
get_tree().quit()
func _on_more_levels_button_pressed():
get_tree().paused = false
get_tree().change_scene_to_file("res://Scenes/UI/game_levels.tscn")
“change_scene_to_file” already changes the scene, why do you want to reload it too?
Yeah but I want to initialize the whole screen. With the the change_scene_to_file my character gets teleported to the checkpoint, so that means it is not fully reloaded.
If you have Global/Autoloads, they are not removed during a change scene, nor reloaded. If your checkpoints are part of a Global script, you will have to disable/overwrite the checkpoint before changing to the next level.
This is the node tree of the First Level :

The checkpoint.gd script that I change the player’s initial position is linked to the Area2D called “Checkpoint”. I don’t know what a Global script is but I don’t think that is one.
checkpoint.gd
extends Area2D
@onready var player = $"../../Player"
@onready var sprite_2d = $Sprite2D
func _on_area_entered(area):
player.spawn_position = self.position + Vector2(0,32)
sprite_2d.modulate = Color.BLACK
Cool, no globals rules out a lot. For future reference they are part of project settings, they go by three names Singletons, Autoloads, and Globals.
Is your checkpoint connected to body_entered
? Or does your player have an Area2D as a child?
I see your checkpoint.gd does not filter what is colliding with it, so if _on_area_entered
is actually connected to the body_entered
signal then the tilemap floor itself will trigger the checkpoint. Here’s a simple name-based way to filter only player collisions (again assuming body_entered
connection)
extends Area2D
@onready var sprite_2d = $Sprite2D
func _on_area_entered(area):
if area.name == "Player":
area.spawn_position = self.position + Vector2(0,32)
sprite_2d.modulate = Color.BLACK
My Player is a CharacterBody2D and has an Area2D as a child.
Edit: I changed the if statement with if area.get_parent().name == "Player":
and the checkpoint collision works like previously.
Let’s back up a bit, before reload_current_scene()
issue. What were you trying to solve? Can you tell the chain of events as-is, I am assuming you play through a level, from the start to the end. Then loading level 2 starts at a checkpoint, and you want it to start at the beginning, where the player is placed in-editor?
What do you expect to happen versus what really happened?
Okay, so I play the level for the first time, I get pass the checkpoint flag(the flag becomes black and the player positions gets changed to the flag). After that, I complete the level and want to restart the level. I use change_scene_to_file
, but I get respawned in the checkpoint flag. So my assumption was that when I change the scene it doesn’t get initialized. That is why I want to change the scene and then reload it.
How does your player respawn, can I see that script? Does it make use of any static variables?
I used a static variable for the spawn_position…
Thanks for helping man!
2 Likes