I was struggling to code a reliable code that switched level once you touched an area2D without doing:

extends Area2D

var level = 1

func on_body_entered(body):
        level += 1
	get_tree().change_scene_to_file("res://lvl_" + str(global.level) + ".tscn")

However that code wouldn't work past level 2 because every time the scene changed, var level returned to one. I tried many fixes, asked BingAI & scoured the internet for something to fix this in Godot 4.x but couldn't find anything.

After a really long time of thinking about it, i ended up with this:

put this on the area2D:

extends Area2D

signal next_level


func _on_body_entered(body):
	next_level.emit()

Put this on the node at the start of the scene:

extends Node2D

@onready var global = get_node("/root/Global")

func _on_lvl_up_next_level():
	global.level += 1
	get_tree().change_scene_to_file("res://lvl_" + str(global.level) + ".tscn")

last but not least, I created an AutoLoad called global which contained this code:

extends Node

var level: int = 1

Now, to make it work for every level, add the second code to the beginning of every scene & attach the signal next_level to them.

you can set the level variable as a variable in an autoload script

Shouldn't static variables in Godot 4.1 solve this now?
Making the level variable static.

    BroTa Perhaps but sometimes a global/autoload singleton might still be more convenient.