A way to make this door reusable?

Godot Version

4.5.1

Question

hello

this is what i have

This Area2D node has for children an Sprite2D, a Label (door_message) and a ColissionShape2D to detect when the player (a CharacterBody2D) enters the Area2D, this node it’s saved as a scene since i want to use it in other scenes to switch levels, i assumed that if i saved it as a scene and placed it into my level scene node tree and then modified the variable destinationin the editor it would work, and it kinda does, but if i want to add another door and change its destination variable, it just takes me to the scene i set first.

What i want is that each individual door node to take me to the individual scene that i set in the editor, is there any way to do that? i’m very new to godot and gdscript.

Here’s what’s happening

I hope i’m being as clear as i can, my english is not very good, please let me know if you require any additional details.

extends Area2D
@onready var door_message: Label = $"door message"
@export var destination: PackedScene = null

func _on_body_entered(body: Node2D) -> void:
	door_message.visible = true

func _process(delta: float) -> void:
	if body_entered and Input.is_action_just_pressed("action"):
		get_parent().get_tree().change_scene_to_packed(destination)
		if destination == null:
			printerr("Destination not selected!")

body_entered is a signal object. Testing it with if will always return true simply because it exists. So both doors have conditions met to execute the if block when the action is pressed. However the first one in the scene tree will always change the scene because its processing code always executes first. The second one will be wiped out by the scene change so it can never get its chance to run its code.

You need to execute the if block only for the door that player actually touches.

Use Area2D::get_overlapping_bodies() instead to determine if the player is in the area. Or maintain a flag that is set/cleared when the player enters/exits the area, and test that flag.

1 Like

Thank you so much! it now works as intended completely, although, i don’t know if i’m doing this correctly but all i did was change that single line and it all works perfectly fine lol, many thanks again :DD

Post the code so we can check.

1 Like

here, i literally just changed the start of the if statement from body_enteredto get_overlapping_bodies()

extends Area2D
@onready var door_message: Label = $"door message"
@export var destination: PackedScene 

func _on_body_entered(body: Node2D) -> void:
	door_message.visible = true

func _process(delta: float) -> void:
	if get_overlapping_bodies() and Input.is_action_just_pressed("action"):
		get_parent().get_tree().change_scene_to_packed(destination)
		if destination == null:
			printerr("Destination not selected!")

and now it works.

It’ll likely stop working properly once you introduce enemies. Any character body that enters the area will cause get_overlapping_bodies() to return a non-empty array. And such array will always evaluate to true.

To make this work properly you need to test if the player body specifically is contained in the array returned by get_overlapping_bodies(). Or set the area collision layer mask to only recognize the player.

2 Likes

i see, i’ll probably take the second approach you suggest and keep working on it, thank you so much for your advice :))